/************************************************/
/*                                              */
/* File        : spy_remote.c                   */
/* Description : Remote spy library             */
/*                                              */
/* Author: Sfiligoi Igor                        */
/*                                              */
/* Created      : 21.07.1997                    */
/* Last modified: 17.09.1997                    */
/*                                              */
/************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <unistd.h>

#include <Error.h>

#include "spy.h"
#include "spy_remote.h"
#include "spyprog_defs.h"

int spy_open_remote(char *socketname,  /* IN : pathname to which the socket is bound */
		    SPY_id *sid)       /* OUT: SPY_id */
{
  struct sockaddr_un sun_me;

  printf("socketname: %s\n",socketname);
  sun_me.sun_family = AF_UNIX;
  strcpy(sun_me.sun_path,socketname);
    
  *sid = (SPY_id) malloc(sizeof(SPY_id_base));

  (*sid)->spy_type = SPY_TYPE_REMOTE;
  (*sid)->last_event_nr = 0;
  (*sid)->cid = socket(AF_UNIX,SOCK_STREAM,0);
  if ((*sid)->cid<0)
    {
      free(*sid);
      ErrorSetF(SPY_ERROR_UNKNOWN,"spy_open_remote","Socket error.");
      return SPY_ERROR_UNKNOWN; 
    }

  if (connect((*sid)->cid,
	      (struct sockaddr *) &sun_me,
	      sizeof(struct sockaddr_un))<0)
    {
      free(*sid);
      ErrorSetF(SPY_ERROR_UNKNOWN,"spy_open_remote","Connect error.");
      return SPY_ERROR_UNKNOWN; 
    }

  return SPY_ERROR_OK;
}

int spy_close_remote(SPY_id sid)
{

  close(sid->cid);

  free(sid);

  return SPY_ERROR_OK;
}


/* read the requested len */
int spy_read(int stream_id,char *buf,int len)
{
  int index,count;

  index = 0;
  for (index=0; index<len;)
    {
      count = read(stream_id,&(buf[index]),len-index);
      if (count<1)
	break;  /* connection closed */

      index+=count;
    }

  return index;
}

int spy_get_remote(SPY_id sid,    /* IN : SPY_id returned by spy_open_remote */
		   char **buf,    /* OUT: pointer to the data */
                                  /* Should be disposed by the caller */
		   int *bufsize)  /* OUT: buffer size */
{
  int count;
  int size;
  int msg[3];
  ((unsigned int *) msg)[0] = RSPYD_MAGIC_NUMBER;
  msg[1] = sid->last_event_nr;

  count = write(sid->cid,msg,2*sizeof(int));
  if (count!=2*sizeof(int))
    {
      *buf = NULL;
      *bufsize = 0;
      ErrorSetF(SPY_ERROR_UNKNOWN,"spy_get_remote","Write failed, connection closed.");
      return SPY_ERROR_UNKNOWN; 
    }

  count = spy_read(sid->cid,(char *) msg,3*sizeof(int));
  if (count!=3*sizeof(int))
    {
      *buf = NULL;
      *bufsize = 0;
      ErrorSetF(SPY_ERROR_UNKNOWN,"spy_get_remote","Read failed, connection closed.");
      return SPY_ERROR_UNKNOWN; 
    }
  
  if (((unsigned int *) msg)[0]!=RSPYD_MAGIC_NUMBER)
    {
      *buf = NULL;
      *bufsize = 0;
      ErrorSetF(SPY_ERROR_UNKNOWN,"spy_get_remote","Invalid magic number.");
      return SPY_ERROR_UNKNOWN; 
    }

  size = msg[2];
  if (size==0)
    {
      *buf = NULL;
      *bufsize = 0;
      return SPY_ERROR_EMPTY;
    }
  sid->last_event_nr = msg[1];
    

  *buf = (char *) malloc(size);

  count = spy_read(sid->cid,*buf,size);
  if (count!=size)
    {
      free(*buf);
      *buf = NULL;
      *bufsize = 0;
      ErrorSetF(SPY_ERROR_UNKNOWN,"spy_get_remote","Read failed, connection closed.");
      return SPY_ERROR_UNKNOWN; 
    }
  *bufsize = size;

  return SPY_ERROR_OK;
}