/*
** pktio.c for  in 
** 
** Made by 
** Login   <vianney@epita.fr>
** 
** Started on  Wed Sep  1 06:39:54 1999 
** Last update Thu Oct 28 20:19:06 1999 
*/
#include <fcntl.h>
#include "pkt.h"
#include "pat_pat.h"
#include "pktio.h"

/* writes a "pkt" to a file descriptor in a portable manner */
t_status			pkt_write(pkt,fd,alloc_proc,free_proc)
t_pkt				*pkt;
int				fd;
t_alloc_proc			alloc_proc;
t_free_proc			free_proc;
{
  t_pkt_io			pkt_io;
  char				patnamebuf[STR_BUFSIZ];
  int				patnamelen;
  t_status			status;
  char				*iobuf;
  int				iolen;
  int				cc;
  char				*ioptr;

  patnamebuf[0] = 0;
  if ((status = pat_to_str(pkt->pat,
			   patnamebuf,
			   sizeof (patnamebuf))) != 0)
    return (status);
  patnamelen = strlen(patnamebuf);
  pkt_io.patnamelen = htonl(patnamelen);
  pkt_io.len = htonl(pkt->len);
  pkt_io.netlen = htonl(pkt->netlen);
  pkt_io.timestamp_sec = htonl(pkt->timestamp.tv_sec);
  pkt_io.timestamp_usec = htonl(pkt->timestamp.tv_usec);
  iolen = sizeof (t_pkt_io) +
    patnamelen +
    pkt->len;
  if ((iobuf = alloc_proc(iolen,
			  "pktio",
			  "pkt_write:buf",
			  &status)) == NULL)
    return (status);
  FBCOPY(&pkt_io,iobuf,sizeof (t_pkt_io));
  FBCOPY(patnamebuf,iobuf + sizeof (t_pkt_io),patnamelen);
  FBCOPY(pkt->buf,iobuf + sizeof (t_pkt_io) + patnamelen,pkt->len);
  ioptr = iobuf;
  while (iolen > 0)
    {
#ifdef DEBUG
      if (PAT_VERB(VERB_PAT_PKTIO))
	fprintf(stderr,"+pktio+ pkt_write: %s %d bytes\n",patnamebuf,iolen);
#endif
      if ((cc = write(fd,ioptr,iolen)) <= 0)
	{
	  free_proc(iobuf,
		    "pktio",
		    "pkt_write:buf");
	  return (ERR_PAT_WRITE);
	}
      ioptr += cc;
      iolen -= cc;
    }
  free_proc(iobuf,
	    "pktio",
	    "pkt_write:buf");
  return (0);
}

/* reads a "pkt" from a file descriptor in a portable manner */
t_status			pkt_read(pkt,fd,alloc_proc,free_proc)
t_pkt				*pkt;
int				fd;
t_alloc_proc			alloc_proc;
t_free_proc			free_proc;
{
  int				cc;
  t_pkt_io			pkt_io;
  char				patnamebuf[STR_BUFSIZ];
  int				patnamelen;
  t_pkt				iopkt;
  char				*iobuf;
  int				iolen;
  t_status			status;

#ifdef DEBUG
  if (PAT_VERB(VERB_PAT_PKTIO))
    fprintf(stderr,"+pktio+ pkt_read: fd=%d\n",fd);
#endif
  if ((cc = read(fd,&pkt_io,sizeof (t_pkt_io))) <= 0)
    return (ERR_PAT_READ);
  if (cc < sizeof (t_pkt_io))
    return (ERR_PAT_PKTIO_PROTOCOL_ERROR);
#ifdef DEBUG
      if (PAT_VERB(VERB_PAT_PKTIO))
	fprintf(stderr,"+pktio+ pkt_read: pktio header (%d bytes)\n",
		sizeof (t_pkt_io));
#endif
  patnamelen = ntohl(pkt_io.patnamelen);
  iopkt.len = ntohl(pkt_io.len);
  iopkt.netlen = ntohl(pkt_io.netlen);
  iopkt.timestamp.tv_sec = ntohl(pkt_io.timestamp_sec);
  iopkt.timestamp.tv_usec = ntohl(pkt_io.timestamp_usec);
  iolen = patnamelen + iopkt.len;
  if ((iobuf = alloc_proc(iolen,
			  "pktio",
			  "pkt_read:buf",
			  &status)) == NULL)
    return (status);
  if ((cc = read(fd,iobuf,iolen)) <= 0)
    {
      status = ERR_PAT_READ;
      goto end;
    }
  if (cc != iolen)
    return (ERR_PAT_PKTIO_PROTOCOL_ERROR);
#ifdef DEBUG
  if (PAT_VERB(VERB_PAT_PKTIO))
    fprintf(stderr,"+pktio+ pkt_read: %d bytes\n",cc);
#endif
  if (patnamelen >= 256)
    {
      status = ERR_PAT_PKTIO_PROTOCOL_ERROR;
      goto end;
    }
  FBCOPY(iobuf,patnamebuf,patnamelen);
  patnamebuf[patnamelen] = 0;
#ifdef DEBUG
  if (PAT_VERB(VERB_PAT_PKTIO))
    fprintf(stderr,
	    "+pktio+ pkt_read: found pat `%s' strlen=%d patnamelen=%d\n",
	    patnamebuf,strlen(patnamebuf),patnamelen);
#endif
  if ((iopkt.pat = pat_from_str(patnamebuf,
				&status)) == NULL)
    {
      goto end;
    }
  iopkt.buf = iobuf + patnamelen;
  status = pkt_scratch(&iopkt,
		       pkt,
		       alloc_proc,
		       free_proc);
end:
  free_proc(iobuf,
	    "pktio",
	    "pkt_read:buf");
#ifdef DEBUG
  if (PAT_VERB(VERB_PAT_PKTIO))
    err_print(status,"+pktio+ pkt_read: returning with status");
#endif
  return (status);
}
