/*
		                  LCRZO
                             Network library
             Copyright(c) 1999,2000,2001,2002 Laurent Constantin
                                  -----

  Main server    : http://www.laurentconstantin.com/
  Backup servers : http://go.to/laurentconstantin/
                   http://laurentconstantin.est-la.com/
                   http://laurentconstantin.free.fr/
                   http://lauconstantin.multimania.com/
  [my current email address is on the web servers]

                                  -----
  This file is part of Lcrzo.

  Lcrzo 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.

  Lcrzo 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 (http://www.gnu.org).

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

/* -- Note about comments and variable names --
   In versions 1.00 up to 2.08, lcrzo was only written in French (my
   mother tongue). Since version 3.00, lcrzo is written in English, but
   most of comments and variable names are still in French.
   In future versions, I'll try to translate everything into English,
   but as you may guess, that's a quite big work...
   So, for the moment, here are some word translation, if you want to
   be able to understand what's going on in the functions :
     afficher - print     ;  ajouter - add         ;  copie - copy
     dernier - last       ;  donnee - data         ;  ecrire - write
     entete - header      ;  envoye - sent         ;  ferme - close
     fichier - file       ;  lire - read           ;  masque - mask 
     nboct - byte number  ;  ouvre, ouvrir - open  ;  paq, paquet - packet
     plage - range        ;  premier - first       ;  recu - received
     reseau - network     ;  retour - return       ;  taille - size
     tunnel - pipe

*/

#include "lcrzo_incl.h"


/*-------------------------------------------------------------*/
#include "sysdep/lcrzo_priv_ipc_writetlv.c"

/*-------------------------------------------------------------*/
#include "sysdep/lcrzo_priv_wait_ipc_wait.c"
#include "sysdep/lcrzo_priv_wait_ipc_read.c"

/*-------------------------------------------------------------*/
int lcrzo_priv_ipc_readwantedtlv(lcrzo_ipc *pipc,
		   lcrzo_time *pmaxwaitingtime,
       lcrzo_uint16 wantedtype,
       lcrzo_int32 wantedsize,
       lcrzo_data *pdata,
       lcrzo_int32 *pdatasize);
int lcrzo_priv_ipc_readwantedtlv(lcrzo_ipc *pipc,
		   lcrzo_time *pmaxwaitingtime,
       lcrzo_uint16 wantedtype,
       lcrzo_int32 wantedsize,
       lcrzo_data *pdata,
       lcrzo_int32 *pdatasize)
{ lcrzo_wait waitread;
  lcrzo_bool mayread;

  lcrzo_er(lcrzo_wait_init_ipc_read(pipc, &waitread));
  lcrzo_er(lcrzo_wait_wait1(&waitread, pmaxwaitingtime, &mayread));
  lcrzo_er(lcrzo_wait_close(&waitread));
  if (!mayread) return(LCRZO_ERR_OKTEMPDATAEND);

  /* read data, and check it corresponds to wanted data */
  lcrzo_er(lcrzo_priv_storedtlvdata_extractifwanted(&(pipc->storeddata), 
						    &(pipc->storeddatasize),
                                                    pipc->dataend, wantedtype,
						    wantedsize, pdata, 
						    pdatasize));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
#include "sysdep/lcrzo_ipc_init.c"

/*-------------------------------------------------------------*/
#if defined LCRZOTEST_HOOK_IPCSIDE
  /* useful for my private tests only */
  int lcrzotest_hook_ipcside=LCRZO_FALSE;
#endif
#include "sysdep/lcrzo_ipc_currentprocessissidea.c"
#include "sysdep/lcrzo_ipc_currentprocessissideb.c"

/*-------------------------------------------------------------*/
#include "sysdep/lcrzo_ipc_close.c"
#include "sysdep/lcrzo_ipc_close_read.c"
#include "sysdep/lcrzo_ipc_close_write.c"

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_uint8(lcrzo_ipc *pipc, lcrzo_uint8 uint8)
{ lcrzo_uint8 donnees[1];
  lcrzo_uint32 nboctdonnees;

  /*parameters verification*/
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);

  /*preparation des donnees a ecrire*/
  donnees[0]=uint8;
  nboctdonnees=1;

  /*ecriture*/
  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_UINT8,
				 donnees, nboctdonnees));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_uint8(lcrzo_ipc *pipc,
		   lcrzo_time *pmaxwaitingtime, 
			 lcrzo_uint8 *puint8)
{ lcrzo_int32 datasize;
  lcrzo_data data;

  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime, LCRZO_PRIV_IPCTYPE_UINT8, 1,
                                        &data, &datasize));

  /* set output */
  if (puint8!=NULL) *puint8 = data[0] ;
  lcrzo_data_free(data);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_uint16(lcrzo_ipc *pipc, lcrzo_uint16 uint16)
{ lcrzo_uint8 donnees[2];
  lcrzo_int32 nboctdonnees;

  /*parameters verification*/
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);

  /*preparation des donnees a ecrire*/
  donnees[0]=(lcrzo_uint8)( (uint16>>8)&0xFF );
  donnees[1]=(lcrzo_uint8)( uint16&0xFF );
  nboctdonnees=2;

  /*ecriture*/
  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_UINT16,
				 donnees, nboctdonnees));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_uint16(lcrzo_ipc *pipc,
		   lcrzo_time *pmaxwaitingtime, 
			 lcrzo_uint16 *puint16)
{ lcrzo_int32 datasize;
  lcrzo_data data;
  
  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime, LCRZO_PRIV_IPCTYPE_UINT16, 2,
                                        &data, &datasize));

  /* set output */
  if (puint16!=NULL) *puint16 = (lcrzo_uint16)( (data[0]<<8) | data[1] );
  lcrzo_data_free(data);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_uint32(lcrzo_ipc *pipc, lcrzo_uint32 uint32)
{ lcrzo_uint8 donnees[4];
  lcrzo_int32 nboctdonnees;

  /*parameters verification*/
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);

  /*preparation des donnees a ecrire*/
  donnees[0]=(lcrzo_uint8)(uint32>>24);
  donnees[1]=(lcrzo_uint8)((uint32>>16)&0xFF);
  donnees[2]=(lcrzo_uint8)((uint32>>8)&0xFF);
  donnees[3]=(lcrzo_uint8)(uint32&0xFF);
  nboctdonnees=4;

  /*ecriture*/
  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_UINT32,
				 donnees, nboctdonnees));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_uint32(lcrzo_ipc *pipc,
			  lcrzo_time *pmaxwaitingtime, 
			 lcrzo_uint32 *puint32)
{ lcrzo_int32 datasize;
  lcrzo_data data;
  
  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime,
					LCRZO_PRIV_IPCTYPE_UINT32, 4,
                                        &data, &datasize));

  /* set output */
  if (puint32!=NULL)
  { *puint32 = (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | data[3] ;
  }
  lcrzo_data_free(data);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_hs(lcrzo_ipc *pipc, const lcrzo_hs hs)
{ lcrzo_hs hscopie;

  /*parameters verification*/
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);

  /*preparation des donnees a ecrire*/
  lcrzo_er(lcrzo_hs_init(hs, hscopie));

  /*ecriture*/
  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_HS,
				 (const lcrzo_uint8 *)hscopie,
				 strlen(hscopie)+1));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_hs(lcrzo_ipc *pipc,
		   lcrzo_time *pmaxwaitingtime, 
		    lcrzo_hs hs)
{ lcrzo_int32 datasize;
  lcrzo_data data;
  int ret;

  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime, LCRZO_PRIV_IPCTYPE_HS, 0,
                                        &data, &datasize));

  /* set output */
  ret=lcrzo_hs_init((const lcrzo_int8 *)data, hs);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_ips(lcrzo_ipc *pipc, const lcrzo_ips ips)
{ lcrzo_ips ipscopie;

  /*parameters verification*/
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);

  /*preparation des donnees a ecrire*/
  lcrzo_er(lcrzo_ips_init(ips, ipscopie));

  /*ecriture*/
  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_IPS,
				 (const lcrzo_uint8 *)ipscopie,
				 strlen(ipscopie)+1));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_ips(lcrzo_ipc *pipc,
		   lcrzo_time *pmaxwaitingtime, 
		     lcrzo_ips ips)
{ lcrzo_int32 datasize;
  lcrzo_data data;
  int ret;

  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime, LCRZO_PRIV_IPCTYPE_IPS, 0,
                                        &data, &datasize));

  /* set output */
  ret=lcrzo_ips_init((const lcrzo_int8 *)data, ips);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_ipa(lcrzo_ipc *pipc, const lcrzo_ipa ipa)
{ 
  /*parameters verification*/
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);
  if (ipa==NULL) return(LCRZO_ERR_PANULLPTR);

  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_IPA,
				 ipa, LCRZO_IPA_MAXBYTES));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_ipa(lcrzo_ipc *pipc,
		   lcrzo_time *pmaxwaitingtime, 
		     lcrzo_ipa ipa)
{ lcrzo_int32 datasize;
  lcrzo_data data;
  
  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime, LCRZO_PRIV_IPCTYPE_IPA, LCRZO_IPA_MAXBYTES,
                                        &data, &datasize));

  /* set output */
  if (ipa!=NULL) memcpy(ipa, data, LCRZO_IPA_MAXBYTES);
  lcrzo_data_free(data);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_ipl(lcrzo_ipc *pipc, lcrzo_ipl ipl)
{ return(lcrzo_ipc_write_uint32(pipc, ipl));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_ipl(lcrzo_ipc *pipc,
		   lcrzo_time *pmaxwaitingtime, 
		     lcrzo_ipl *pipl)
{ return(lcrzo_ipc_read_uint32(pipc, pmaxwaitingtime, pipl));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_eths(lcrzo_ipc *pipc, const lcrzo_eths eths)
{ lcrzo_eths ethscopie;

  /*parameters verification*/
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);

  /*preparation des donnees a ecrire*/
  lcrzo_er(lcrzo_eths_init(eths, ethscopie));

  /*ecriture*/
  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_ETHS,
				 (const lcrzo_uint8 *)ethscopie, 
				 strlen(ethscopie)+1));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_eths(lcrzo_ipc *pipc,
		   lcrzo_time *pmaxwaitingtime, 
		     lcrzo_eths eths)
{ lcrzo_int32 datasize;
  lcrzo_data data;
  int ret;

  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime, LCRZO_PRIV_IPCTYPE_ETHS, 0,
                                        &data, &datasize));

  /* set output */
  ret=lcrzo_eths_init((const lcrzo_int8 *)data, eths);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_etha(lcrzo_ipc *pipc, const lcrzo_etha etha)
{
  /*parameters verification*/
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);
  if (etha==NULL) return(LCRZO_ERR_PANULLPTR);

  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_ETHA,
				 etha, LCRZO_ETHA_MAXBYTES));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_etha(lcrzo_ipc *pipc,
		   lcrzo_time *pmaxwaitingtime, 
		     lcrzo_etha etha)
{ lcrzo_int32 datasize;
  lcrzo_data data;
  
  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime, LCRZO_PRIV_IPCTYPE_ETHA, LCRZO_ETHA_MAXBYTES,
                                        &data, &datasize));

  /* set output */
  if (etha!=NULL) memcpy(etha, data, LCRZO_ETHA_MAXBYTES);
  lcrzo_data_free(data);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_device(lcrzo_ipc *pipc, const lcrzo_device device)
{ lcrzo_device devicecopie;

  /*parameters verification*/
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);

  /*preparation des donnees a ecrire*/
  lcrzo_er(lcrzo_device_init(device, devicecopie));

  /*ecriture*/
  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_DEVICE,
				 (const lcrzo_uint8 *)devicecopie, 
				 strlen(devicecopie)+1));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_device(lcrzo_ipc *pipc,
		          lcrzo_time *pmaxwaitingtime, 
			  lcrzo_device device)
{ lcrzo_int32 datasize;
  lcrzo_data data;
  int ret;

  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime, LCRZO_PRIV_IPCTYPE_DEVICE, 0,
                                        &data, &datasize));

  /* set output */
  ret=lcrzo_device_init((const lcrzo_int8 *)data, device);
  lcrzo_data_free(data);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_ipc_write_deviceethaiplport(lcrzo_ipc *pipc,
				      const lcrzo_device device,
				      const lcrzo_etha etha,
				      lcrzo_ipl ipl,
				      lcrzo_uint16 port)
{ lcrzo_uint8 array[LCRZO_DEVICE_MAXBYTES+LCRZO_ETHA_MAXBYTES+LCRZO_IPA_MAXBYTES+2];
  lcrzo_ipa ipa;
  int arrayindex;

  /* parameters verification */
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);
  if (device==NULL) return(LCRZO_ERR_PANULLPTR);
  if (etha==NULL) return(LCRZO_ERR_PANULLPTR);

  /* copy items in the array */
  memcpy(array, device, LCRZO_DEVICE_MAXBYTES);
  arrayindex=LCRZO_DEVICE_MAXBYTES;
  memcpy(array+arrayindex, etha, LCRZO_ETHA_MAXBYTES);
  arrayindex+=LCRZO_ETHA_MAXBYTES;
  lcrzo_er(lcrzo_ipa_init_ipl(ipl, ipa));
  memcpy(array+arrayindex, ipa, LCRZO_IPA_MAXBYTES);
  arrayindex+=LCRZO_IPA_MAXBYTES;
  array[arrayindex++]=(lcrzo_uint8)(port>>8);
  array[arrayindex++]=(lcrzo_uint8)(port&0xFF);

  /* write data to ipc */
  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_CO_DEIP,
				 array, arrayindex));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_deviceethaiplport(lcrzo_ipc *pipc, 
				     lcrzo_time *pmaxwaitingtime, 
			             lcrzo_device device,
				     lcrzo_etha etha,
				     lcrzo_ipl *pipl,
				     lcrzo_uint16 *pport)
{ lcrzo_int32 datasize;
  lcrzo_data data;
  lcrzo_ipa ipa;
  int arrayindex;

  /* read from ipc */
  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime, LCRZO_PRIV_IPCTYPE_CO_DEIP,
                                        LCRZO_DEVICE_MAXBYTES+LCRZO_ETHA_MAXBYTES+LCRZO_IPA_MAXBYTES+2,
                                        &data, &datasize));

  /* set output */
  lcrzo_er(lcrzo_device_init((const lcrzo_int8 *)data, device));
  arrayindex=LCRZO_DEVICE_MAXBYTES;
  if (etha!=NULL)
  { memcpy(etha, data+arrayindex, LCRZO_ETHA_MAXBYTES);
  }
  arrayindex+=LCRZO_ETHA_MAXBYTES;
  if (pipl!=NULL)
  { memcpy(ipa, data+arrayindex, LCRZO_IPA_MAXBYTES);
    lcrzo_er(lcrzo_ipl_init_ipa(ipa, pipl));
  }
  arrayindex+=LCRZO_IPA_MAXBYTES;
  if (pport!=NULL)
  { *pport= (lcrzo_uint16)(data[arrayindex]<<8 | data[arrayindex+1]);
  }
  lcrzo_data_free(data);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_ethaiplport(lcrzo_ipc *pipc,
				const lcrzo_etha etha,
				lcrzo_ipl ipl,
				lcrzo_uint16 port)
{ lcrzo_uint8 array[LCRZO_ETHA_MAXBYTES+LCRZO_IPA_MAXBYTES+2];
  lcrzo_ipa ipa;
  int arrayindex;

  /* parameters verification */
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);
  if (etha==NULL) return(LCRZO_ERR_PANULLPTR);

  /* copy items in the array */
  memcpy(array, etha, LCRZO_ETHA_MAXBYTES);
  arrayindex=LCRZO_ETHA_MAXBYTES;
  lcrzo_er(lcrzo_ipa_init_ipl(ipl, ipa));
  memcpy(array+arrayindex, ipa, LCRZO_IPA_MAXBYTES);
  arrayindex+=LCRZO_IPA_MAXBYTES;
  array[arrayindex++]=(lcrzo_uint8)(port>>8);
  array[arrayindex++]=(lcrzo_uint8)(port&0xFF);

  /* write data to ipc */
  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_CO_EIP,
				 array, arrayindex));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_ethaiplport(lcrzo_ipc *pipc, 
			       lcrzo_time *pmaxwaitingtime, 
			       lcrzo_etha etha,
			       lcrzo_ipl *pipl,
			       lcrzo_uint16 *pport)
{ lcrzo_int32 datasize;
  lcrzo_data data;
  lcrzo_ipa ipa;
  int arrayindex;

  /* read from ipc */
  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime, LCRZO_PRIV_IPCTYPE_CO_EIP,
                                        LCRZO_ETHA_MAXBYTES+LCRZO_IPA_MAXBYTES+2,
                                        &data, &datasize));

  /* set output */
  if (etha!=NULL)
  { memcpy(etha, data, LCRZO_ETHA_MAXBYTES);
  }
  arrayindex=LCRZO_ETHA_MAXBYTES;
  if (pipl!=NULL)
  { memcpy(ipa, data+arrayindex, LCRZO_IPA_MAXBYTES);
    lcrzo_er(lcrzo_ipl_init_ipa(ipa, pipl));
  }
  arrayindex+=LCRZO_IPA_MAXBYTES;
  if (pport!=NULL)
  { *pport= (lcrzo_uint16)(data[arrayindex]<<8 | data[arrayindex+1]);
  }
  lcrzo_data_free(data);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write_iplport(lcrzo_ipc *pipc,
			    lcrzo_ipl ipl,
			    lcrzo_uint16 port)
{ lcrzo_uint8 array[LCRZO_IPA_MAXBYTES+2];
  int arrayindex;

  /* parameters verification */
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);

  /* copy items in the array */
  lcrzo_er(lcrzo_ipa_init_ipl(ipl, array));
  arrayindex=LCRZO_IPA_MAXBYTES;
  array[arrayindex++]=(lcrzo_uint8)(port>>8);
  array[arrayindex++]=(lcrzo_uint8)(port&0xFF);

  /* write data to ipc */
  return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_CO_IP,
				 array, arrayindex));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_read_iplport(lcrzo_ipc *pipc, 
			   lcrzo_time *pmaxwaitingtime, 
			   lcrzo_ipl *pipl,
			   lcrzo_uint16 *pport)
{ lcrzo_int32 datasize;
  lcrzo_data data;
  lcrzo_ipa ipa;
  int arrayindex;

  /* read from ipc */
  lcrzo_er(lcrzo_priv_ipc_readwantedtlv(pipc, pmaxwaitingtime, LCRZO_PRIV_IPCTYPE_CO_IP,
                                        LCRZO_IPA_MAXBYTES+2,
                                        &data, &datasize));

  /* set output */
  if (pipl!=NULL)
  { memcpy(ipa, data, LCRZO_IPA_MAXBYTES);
    lcrzo_er(lcrzo_ipl_init_ipa(ipa, pipl));
  }
  arrayindex=LCRZO_IPA_MAXBYTES;
  if (pport!=NULL)
  { *pport= (lcrzo_uint16)(data[arrayindex]<<8 | data[arrayindex+1]);
  }
  lcrzo_data_free(data);
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_ipc_write_msg(lcrzo_ipc *pipc,
			lcrzo_constdata data,
			lcrzo_int32 datasize)
{ return(lcrzo_priv_ipc_writetlv(pipc, LCRZO_PRIV_IPCTYPE_MSG,
				 data, datasize));
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_write(lcrzo_ipc *pipc,
		    lcrzo_constdata data,
		    lcrzo_int32 datasize)
{ lcrzo_int32 blocksize, i;
  
  /*parameters verification*/
  if (pipc==NULL) return(LCRZO_ERR_PANULLPTR);

  for ( i=0 ; i<datasize ; )
  { /*determine block size*/
    blocksize=datasize-i;
    if (blocksize>LCRZO_PRIV_WRITEMAXMSGSIZE)
      blocksize=LCRZO_PRIV_WRITEMAXMSGSIZE;
    /*write a block*/
    lcrzo_er(lcrzo_ipc_write_msg(pipc, data+i, blocksize));
    /*update the current position*/
    i+=blocksize;
  }

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_readm(lcrzo_ipc *pipc, 
		   lcrzo_time *pmaxwaitingtime, 
		    lcrzo_data *pdataout,
		    lcrzo_int32 *pdataoutsize)
{ lcrzo_wait waitread;
  lcrzo_bool mayread;
  
  lcrzo_er(lcrzo_wait_init_ipc_read(pipc, &waitread));
  lcrzo_er(lcrzo_wait_wait1(&waitread, pmaxwaitingtime, &mayread));
  lcrzo_er(lcrzo_wait_close(&waitread));
  if (!mayread) return(LCRZO_ERR_OKTEMPDATAEND);
  
  /* read data, and check it corresponds to wanted data */
  lcrzo_er(lcrzo_priv_storedtlvdata_extract(&(pipc->storeddata),
					    &(pipc->storeddatasize), 
                                            pipc->dataend, pdataout,
					    pdataoutsize));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_readm_fixed(lcrzo_ipc *pipc, 
		   lcrzo_time *pmaxwaitingtime, 
			  lcrzo_int32 datasizetoread,
			  lcrzo_data *pdataout)
{ lcrzo_wait waitread;
  lcrzo_bool mayread;
  
  lcrzo_er(lcrzo_wait_init_ipc_read_fixed(pipc, datasizetoread, &waitread));
  lcrzo_er(lcrzo_wait_wait1(&waitread, pmaxwaitingtime, &mayread));
  lcrzo_er(lcrzo_wait_close(&waitread));
  if (!mayread) return(LCRZO_ERR_OKTEMPDATAEND);

  /* read data, and check it corresponds to wanted data */
  lcrzo_er(lcrzo_priv_storedtlvdata_extract_fixed(&(pipc->storeddata),
						  &(pipc->storeddatasize), 
                                                  pipc->dataend, 
						  datasizetoread, pdataout));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipc_readm_line(lcrzo_ipc *pipc, 
		   lcrzo_time *pmaxwaitingtime, 
			 lcrzo_data *pdataout,
			 lcrzo_int32 *pdataoutsize)
{ lcrzo_wait waitread;
  lcrzo_bool mayread;
  
  lcrzo_er(lcrzo_wait_init_ipc_read_line(pipc, &waitread));
  lcrzo_er(lcrzo_wait_wait1(&waitread, pmaxwaitingtime, &mayread));
  lcrzo_er(lcrzo_wait_close(&waitread));
  if (!mayread) return(LCRZO_ERR_OKTEMPDATAEND);

  /* read data, and check it corresponds to wanted data */
  lcrzo_er(lcrzo_priv_storedtlvdata_extract_line(&(pipc->storeddata),
						 &(pipc->storeddatasize), 
                                                 pipc->dataend, pdataout, 
						 pdataoutsize));
  return(LCRZO_ERR_OK);
}





