/*
 *   Copyright (C) 1992 by the Massachusetts Institute of Technology
 *   All rights reserved.
 *
 *   For copying and distribution information, please see the file
 *   COPYRIGHT.
 */

#include "v.h"
#include<stdio.h>


#ifdef MacOS
#include<bsd-mac-compat.h>
#else
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#endif

#if defined(MacOS) || defined(MSDOS)		/* Macintosh/MSDOS client? */
#include <string.h>
#endif /* MacOS || MSDOS */

static void v_parse_pkt_data (char *data, char *end, char **record, 
			      int numfields)
	{
	while (numfields--) 
		{
		*record++ = data;
		while (data < end && *data++);
		}
	}

v_parse_pkt (struct v_pkt *pkt,
	     struct v_info *info)
	{
	v_parse_pkt_data(pkt->data, pkt->data + V_MAXDATA - 1,
			 (char **) info, sizeof(struct v_info)/sizeof(char *));
	}

int v_read_pkt (int sock, struct v_pkt *pkt, struct v_info *info,
		struct sockaddr *sa, int *sockaddr_len)
{
  int rc;
  
  rc = recvfrom(sock, (char *) pkt, sizeof(struct v_pkt), 0, sa, sockaddr_len);
  if (rc <= 0) return -1;
  pkt->protocol_version = ntohs (pkt->protocol_version);
  pkt->packet_number = ntohs (pkt->packet_number);
  pkt->number_of_packets = ntohs (pkt->number_of_packets);
  pkt->op_code = ntohs (pkt->op_code);
  pkt->seq = ntohl (pkt->seq);
  if (pkt->op_code != V_ERROR)
    v_parse_pkt (pkt, info);
  else
     memset(info, 0, sizeof(struct v_info));
  return 0;
}
     
static int v_assemble_pkt_data (char *target, char *end, char **fields, int numfields)
{
  char *first = target;
  
  while (numfields--) {
    if (*fields == NULL)		/* If no string is supplied... */
      *target++ = 0;			/* ...then put in a string of length 0 */
    else
      strncpy(target, *fields, end - target);
    target = (char *)strrchr(target, 0) + 1;
    fields++;
  }
  return (target - first);
}


/*
 * v_assemble_pkt --- make a packet out of the data, returning the
 * total size of the packet
 */

int v_assemble_pkt (struct v_pkt *pkt,
		    struct v_info *info)
{
  int numfields = sizeof(struct v_info)/sizeof(char *);
  return
    (v_assemble_pkt_data (pkt->data, pkt->data + V_MAXDATA - numfields,
			  (char **) info, numfields)
     + V_BASE_SIZE);     
}
