#include <stdio.h>
#include "Error.h"
#include "Connect.h"
#include "protocol.h"
#include <netinet/in.h>

/* If protocol.h changes... */
char *protoTypes[14] = {
  "Error",
  "Orientation request",
  "Orientation response",
  "Access initialize",
  "Access change",
  "Access response",
  "Access upgrade",
  "Status query",
  "Status response",
  "Security",
  "State",
  "State reply",
  "Reduce",
  "Reduce reply"
  };

/*
 * ERRORS:
 *
 * PROTO_PACKETTOOSHORT: FATAL
 * The protocol claimed the packet was longer than what was received.
 *
 * PROTO_ENDPACKET: FATAL
 * The packet received was too short to contain the requested item.
 *
 * PROTO_MISMATCH: FATAL
 * The protocol of the packet did not match.
 */
Trap P0_GetHeader(packet)
     P0Packet *packet;
{
  Card16 *ptr;

  ptr = (Card16 *)packet->packet->packet; /* heh */

  if (packet->packet->length < 8)
    Return(PROTO_ENDPACKET, NULL);

  packet->version = ntohs(*ptr);	ptr++;
  packet->type = ntohs(*ptr);		ptr++;
  packet->context = ntohs(*ptr);	ptr++;
  packet->length = ntohs(*ptr);		ptr++;

  if (packet->length > packet->packet->length)
    Return(PROTO_PACKETTOOSHORT, NULL);

  if (packet->version != 0)
    Return(PROTO_MISMATCH, NULL);

  packet->current = (char *)ptr;
  packet->end = packet->length + packet->packet->packet;
  return OK;
}

Trap P0_PutHeader(packet)
     P0Packet *packet;
{
  Card16 *ptr;

  packet->version = 0;
  packet->length = 8;
  ptr = (Card16 *)packet->packet->packet;

  *ptr = htons(packet->version);	ptr++;
  *ptr = htons(packet->type);		ptr++;
  *ptr = htons(packet->context);	ptr++;
/**ptr = htons(packet->length);	*/	ptr++;

  packet->end = (char *)ptr;
  return OK;
}

Trap P0_PutLength(packet)
     P0Packet *packet;
{
  packet->packet->length = packet->end - packet->packet->packet;
  *(short *)(&(packet->packet->packet[6])) =
    htons((short)(packet->packet->length));

  return OK;
}

Trap P0_GetString(packet, string)
     P0Packet *packet;
     char **string;
{
  char *s;

  s = packet->current;
  while (s < packet->end && *s != '\0') s++;

  if (s == packet->end)
    Return(PROTO_ENDPACKET, NULL);

  *string = packet->current;
  packet->current = s + 1;
  return OK;
}

Trap P0_PutString(packet, string)
     P0Packet *packet;
     char *string;
{
  char *s;

  if (string == NULL)
    Return(BOZO_NULLPOINTER, NULL);

  s = packet->end;
  while (*string != '\0')
    *s++ = *string++;

  *s++ = '\0';
  packet->end = s;

  return OK;
}

Trap P0_GetCard16(packet, card)
     P0Packet *packet;
     Card16 *card;
{
  char *s;

  s = packet->current;
  if ((int)(s) & 1) s++;		/* auto padding */

  if (packet->end - s < 2)
    Return(PROTO_ENDPACKET, NULL);

  *card = ntohs(*(Card16 *)s);
  packet->current = s + 2;
  return OK;
}

Trap P0_PutCard16(P0Packet *packet, Card16 card)
/*
Trap P0_PutCard16(packet, card)
     P0Packet *packet;
     Card16 card;
*/
{
  char *s;

  s = packet->end;
  if ((int)(s) & 1) s++;		/* auto padding */

  *(Card16 *)s = htons(card);
  packet->end = s + 2;
  return OK;
}

Trap P0_GetCard32(packet, card)
     P0Packet *packet;
     Card32 *card;
{
  char *l;

  l = packet->current;
  if ((int)(l) & 3) l += 4 - ((int)(l) & 3);	/* auto padding */

  if (packet->end - l < 4)
    Return(PROTO_ENDPACKET, NULL);

  *card = ntohl(*(Card32 *)l);
  packet->current = l + 4;
  return OK;
}

Trap P0_PutCard32(packet, card)
     P0Packet *packet;
     Card32 card;
{
  char *l;

  l = packet->end;
  if ((int)(l) & 3) l += 4 - ((int)(l) & 3);	/* auto padding */

  *(Card32 *)l = htonl(card);
  packet->end = l + 4;
  return OK;
}
