/*===========================================================================
  Copyright (C) 1995-2009 European Southern Observatory (ESO)
 
  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., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/


/*++++++++++++++++++ osx (socket) based client interfaces +++++++++++++++++++
.LANGUAGE C
.IDENTIFICATION Module consubs.c
.AUTHOR         K. Banse                ESO - Garching
.KEYWORDS       background Midas, communication
.ENVIRONMENT    UNIX only
.COMMENTS
holds ClientInit, ClientClose, ClientFree, Clientinfo, ClientWait,
      ClientWrite, ClientRead, ClientKWrite, ClientKRead
      ida_vuelta
.REMARKS
the corresponding server interfaces are in /midas/version/monit/prepz1.c

.VERSION  [1.00] 940425: creation
.VERSION  [1.05] 941018: use serv_buf.code_id as function code

 090407		last modif
----------------------------------------------------------------------------*/

#include <stdlib.h>
#include <midas_def.h>
#include <idiserver.h>
#include <xconndef.h>
#include <fsydef.h>

#define CLIENT_OVF   -99

static char   *servname[2] = { (char *)NULL, (char *)NULL };

static int    first_bytes;
static int    osxclid[MAX_BACK] =
              {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};	/* sync with xconndef.h! */


/*

*/

int ida_vuelta(flag,idclient,size,retosx)
int flag;               /* IN: = 1, write + read   \
                               = 2, write only     \
                               = 3, read only     */
int  idclient;          /* IN: channel no. of client */
int  *size;             /* IN: size of return package in bytes */
int  *retosx;


{
int    osx_cod;
int    osxchan, n_bytes;


osxchan = osxclid[idclient];

if (flag != 3)			/* write into socket */
   {
   osx_cod = osxwrite(osxchan,(char *)&serv_buf,serv_buf.nobyt);

   if (osx_cod <= 0)
      {
      *retosx = oserror;
      return (-1);
      }
   }


if (flag != 2)			/* read from socket */
   {
   osx_cod = osxread (osxchan,(char *)&serv_ret,first_bytes);
   if (osx_cod == -1)
      {
      *retosx = oserror;
      return (-1);
      }
   else if (osx_cod == 1)			/* connection was closed */
      return (1);

   n_bytes = serv_ret.nobyt - RET_SIZE;    /*  get remaining bytes  */
   }
else
   n_bytes = 0;


if (n_bytes > 0)
   {
   osx_cod = osxread(osxchan,(char *)&serv_ret.data,n_bytes);
   if (osx_cod == -1)
      {
      *retosx = oserror;
      return(-1);
      }
   }

*size = n_bytes;		/* return actual no. of returned bytes */
return (0);
}
/*

*/

int ClientInit(shost,sunit,idclient,retosx)
char   *shost, *sunit;
int    *idclient;
int    *retosx;

{
int    osxchan, port;
int    jsecs, msecs, jindx;
int    i, mode;

 
for (i=0; i<MAX_BACK; i++)
   {
   if (osxclid[i] == -1)
      {
      jindx = i;
      goto init_start;
      }
   }
return (CLIENT_OVF);


init_start:
first_bytes = BUFHEAD;
jsecs = 1;
msecs = 0;

if (shost[0] == '\0')
   {
   char   *pipedir, filename[128];

   if (!(pipedir = getenv("MID_WORK")))
      {
      (void) printf
            ("ClientInit: MID_WORK not defined - we use $HOME/midwork/ ...\n");
      if (!(pipedir = getenv("HOME"))) return (-1);

      (void) strcpy(filename,pipedir);
      (void) strcat(filename,"/midwork");
      }
   else
      (void) strcpy(filename,pipedir);

   (void) strcat(filename,"/Midas_osx");
   (void) strcat(filename,sunit);	/* filename: $MID_WORK/Midas_osxXY */
   i = (int)strlen(filename) + 1;
   servname[0] = malloc((size_t)i);
   (void)strcpy(servname[0],filename);
   mode = LOCAL | IPC_WRITE;
   }
else
   {
   i = (int)strlen(BASE_PORT) + 1;
   servname[0] = malloc((size_t)i);
   if ( (port = osxgetservbyname(BASE_SERVICE)) == -1)
      (void)sprintf(servname[0],"%d",atoi(BASE_PORT) + atoi(sunit));
   else
      (void)sprintf(servname[0],"%d",port + atoi(sunit));

   i = (int)strlen(shost) + 1;
   servname[1] = malloc((size_t)i);
   strcpy (servname[1],shost); 
   mode = NETW | IPC_WRITE;
   }


/* Open server channel for reading. */

osxchan = osxopen(servname, mode);


free(servname[0]);
free(servname[1]);
if ( osxchan == -1)
   {				/* we need to look at `oserror' */
   *retosx = oserror;
   if (oserror == -1)
      (void) printf("ClientInit: osxopen produced: %s\n",oserrmsg);
   else
      (void) printf("ClientInit: osxopen produced: %s\n",osmsg());
   return(-1);
   }


osxclid[jindx] = osxchan;
*idclient = jindx;

memset((char *)&serv_buf,0,sizeof(serv_buf));   /* init structures */
memset((char *)&serv_ret,0,sizeof(serv_ret));

serv_buf.code_id = 0;
return(0);
} 

/*

*/
      
void ClientFree()

{
int  i;

for (i=0; i<MAX_BACK; i++)
   osxclid[i] = -1;
}



int ClientInfo(idclient,fd)               /* get info about socket in use */
int    idclient, *fd;

{
if ((idclient < 0) || (idclient >= MAX_BACK)) return (-9);

*fd = osxclid[idclient];

return (0);
}



int ClientClose(idclient,retosx)               /* close connection to server */
int    idclient, *retosx;

{
int    osxchan, kk;

if ((idclient < 0) || (idclient >= MAX_BACK)) return (-9);
osxchan = osxclid[idclient];
osxclid[idclient] = -1;			/* free entry again */
kk = osxclose (osxchan);
if (kk != 0) *retosx = oserror;
   
return(kk);
}

/*

*/

int ClientWait(idclient,timo)
int  idclient, timo;

{
int  osxchan;
int  jsecs, msecs;
int  np;


if ((idclient < 0) || (idclient >= MAX_BACK)) return (-9);
osxchan = osxclid[idclient];


if (timo < 0)			/* -1 = wait until we get data */
   {
   jsecs = 0;
   msecs = 100;

osx_poll:
   np = osxinfo(osxchan,jsecs,msecs);
   if ((np == NOCONN) || (np == -1))
      return (-1);			/* no connection ! */

   if (np != DATARDY) goto osx_poll;
   return (1);			/* we got data */
   }

else
   {
   jsecs = timo;
   msecs = 0;
   np = osxinfo(osxchan,jsecs,msecs);
   if ((np == NOCONN) || (np == -1))
      return (-1);			/* no connection ! */

   if (np == DATARDY)
      return (1);			/* we got data */
   else 
      return (0);			/* NODATA */
   }
}

/*

*/

int ClientWrite(idclient,comline,retosx)
int    idclient;
char   *comline;
int    *retosx;
  
{
int    txtlen, np, myret;
int    retsize;

char   *charbuf;


if ((idclient < 0) || (idclient >= MAX_BACK)) return (-9);

txtlen = (int)strlen(comline) + 1;
np = ((txtlen % III_SIZE) == 0) ? (txtlen/III_SIZE) : (txtlen/III_SIZE + 1);

serv_buf.nobyt   = np*III_SIZE + BUFHEAD;
serv_buf.code_id = 10;
  
charbuf = (char *)(serv_buf.data.in);
(void)strcpy(charbuf,comline);

np = ida_vuelta(2,idclient,&retsize,&myret);		/* don't wait */

if (np != 0) *retosx = myret;
return (np);

}

/*

*/

int ClientRead(idclient,comline,bgstat,retosx)
int    idclient;
char   *comline;
int    *bgstat;
int    *retosx;

{
int    np, retsize, myret;



if ((idclient < 0) || (idclient >= MAX_BACK)) return (-9);

np = ida_vuelta(3,idclient,&retsize,&myret);            /* wait for return */
if (np != 0) *retosx = myret;

*bgstat = serv_ret.code;        /* status of command executed by server */
return (np);

}

/*

*/

int ClientKWrite(idclient,typ,comline,sendbuf,karr,retosx)
int    idclient;
int    typ;
char   *comline;
char   *sendbuf;
int    *karr;                   /* 4 elements */
int    *retosx;

{
register int  nr;
int    retsize;
int    txtlen, np, myret, m;

char   *charbuf;


if ((idclient < 0) || (idclient >= MAX_BACK)) return (-9);

txtlen = (int)strlen(comline) + 1;
np = ((txtlen % III_SIZE) == 0) ? (txtlen/III_SIZE) : (txtlen/III_SIZE + 1);

serv_buf.nobyt = np*III_SIZE + BUFHEAD;
serv_buf.code_id = 20;

charbuf = (char *)(serv_buf.data.in);
(void)strcpy(charbuf,comline);

np = ida_vuelta(1,idclient,&retsize,&myret);            /* send 1. part */

if (np != 0)
   {
   *retosx = myret;
   return (np);
   }

for (nr=0; nr<4; nr++)
   serv_buf.data.in[nr] = karr[nr];

if (typ == 1)
   {
   int    *ipntr;

   ipntr = (int *) sendbuf;
   for (nr=4; nr<karr[0]+4; nr++)
      serv_buf.data.in[nr] = *ipntr++;
   m = (karr[0]+4)*III_SIZE;
   }
else if (typ == 2)
   {
   float  *fpntr;

   fpntr = (float *) sendbuf;
   for (nr=4; nr<karr[0]+4; nr++)
      serv_buf.data.fl[nr] = *fpntr++;
   m = (karr[0]+4)*RRR_SIZE;
   }
else if (typ == 4)
   {
   double *dpntr;

   dpntr = (double *) sendbuf;
   for (nr=4; nr<karr[0]+4; nr++)
      serv_buf.data.db[nr] = *dpntr++;
   m = (karr[0]+4)*DDD_SIZE;
   }
else
   {
   char *cpntr;

   cpntr = (char *) &serv_buf.data.in[4];
   m = karr[0];
   (void)strncpy(cpntr,sendbuf,m);
   m += 4*III_SIZE;
   }

serv_buf.nobyt = m + BUFHEAD;
serv_buf.code_id = 21;

np = ida_vuelta(1,idclient,&retsize,&myret);            /* send 2. part */
if (np != 0)
   *retosx = myret;
else
   {
   for (nr=0; nr<4; nr++)
      karr[nr] = serv_ret.data.in[nr];
   }

return (np);

}
/*

*/

int ClientKRead(idclient,typ,comline,retbuf,karr,retosx)
int    idclient;
int    typ;
char   *comline;
char   *retbuf;
int    *karr;			/* 4 elements */
int    *retosx;
 
{
register int  nr;
int    retsize;
int    txtlen, np, myret;

char   *charbuf;



if ((idclient < 0) || (idclient >= MAX_BACK)) return (-9);

txtlen = (int)strlen(comline) + 1;

np = ((txtlen % III_SIZE) == 0) ? (txtlen/III_SIZE) : (txtlen/III_SIZE + 1);

serv_buf.nobyt   = np*III_SIZE + BUFHEAD;
serv_buf.code_id = 30;
 
charbuf = (char *)(serv_buf.data.in);
(void)strcpy(charbuf,comline);

np = ida_vuelta(1,idclient,&retsize,&myret);             /* write + read */

if (np != 0)
   *retosx = myret;
else
   {
   for (nr=0; nr<4; nr++)
      karr[nr] = serv_ret.data.in[nr];

   if (typ == 1)
      {
      int    *ipntr;

      ipntr = (int *) retbuf;
      for (nr=4; nr<karr[0]+4; nr++)
         *ipntr++ = serv_ret.data.in[nr];
      }
   else if (typ == 2)
      {
      float  *fpntr;

      fpntr = (float *) retbuf;
      for (nr=4; nr<karr[0]+4; nr++)
         *fpntr++ = serv_ret.data.fl[nr];
      }
   else if (typ == 4)
      {
      double *dpntr;

      dpntr = (double *) retbuf;
      for (nr=4; nr<karr[0]+4; nr++)
         *dpntr++ = serv_ret.data.db[nr];
      }
   else
      {
      char  *cpntr;

      cpntr = (char *) &serv_ret.data.in[4];
      (void)strncpy(retbuf,cpntr,karr[0]);
      }
   }

return (np);
}
  
