/*

udpserver.c

SOAP-over-UDP demo server

--------------------------------------------------------------------------------
gSOAP XML Web services tools
Copyright (C) 2001-2004, Robert van Engelen, Genivia, Inc. All Rights Reserved.
This software is released under one of the following two licenses:
GPL or Genivia's license for commercial use.
--------------------------------------------------------------------------------
GPL license.

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., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA

Author contact information:
engelen@genivia.com / engelen@acm.org
--------------------------------------------------------------------------------
A commercial use license is available from Genivia, Inc., contact@genivia.com
--------------------------------------------------------------------------------
*/

#include "soapH.h"
#include "udp.nsmap"

#define MAX_HISTORY (1000)

char *received_id[MAX_HISTORY];
int last_received;
void init_received();
int check_received(const char *id);

int id_count = 1;

int main()
{ struct soap soap;
  init_received();
  soap_init1(&soap, SOAP_IO_UDP);
  if (!soap_valid_socket(soap_bind(&soap, NULL, 10000, 100)))
  { soap_print_fault(&soap, stderr);
    exit(1);
  }
  for (;;)
  { printf("Accepting requests...\n");
    if (soap_serve(&soap))
      soap_print_fault(&soap, stderr);
    soap_end(&soap);
  }
  soap_done(&soap);
  return 0;
}

void init_received()
{ int i;
  for (i = 0; i < MAX_HISTORY; i++)
    received_id[i] = NULL;
  last_received = 0;
}

int check_received(const char *id)
{ int i;
  if (!id)
    return 1;
  /* Check if Message ID already received */
  for (i = 0; i < MAX_HISTORY; i++)
  { if (received_id[i] && !strcmp(id, received_id[i]))
      return 1;
  }
  if (received_id[last_received])
    free(received_id[last_received]);
  received_id[last_received++] = strdup(id);
  /* Wrap to overwrite old IDs */
  if (last_received >= MAX_HISTORY)
    last_received = 0;
  return 0;
}

int check_header(struct soap *soap)
{ /* MUST have received a SOAP Header */
  if (!soap->header)
    return soap_sender_fault(soap, "No SOAP header", NULL);
  /* ... with a Message ID */
  if (!soap->header->wsa__MessageID)
    return soap_sender_fault(soap, "No WS-Addressing MessageID", NULL);
  soap->header->wsa__RelatesTo = (struct wsa__Relationship*)soap_malloc(soap, sizeof(struct wsa__Relationship));
  soap_default_wsa__Relationship(soap, soap->header->wsa__RelatesTo);
  soap->header->wsa__RelatesTo->__item = soap->header->wsa__MessageID;
  return SOAP_OK;
}

int ns__echoString(struct soap *soap, char *str, char **res)
{ /* Get Header info and setup response Header */
  if (check_header(soap))
  { printf("Malformed header\n");
    return SOAP_FAULT; /* there was a problem */
  }

  /* If message with MessageID already received, ignore it */
  if (check_received(soap->header->wsa__MessageID))
  { printf("Request message %s already received\n", soap->header->wsa__MessageID);
    return SOAP_STOP;
  }

  printf("Request message %s accepted\n", soap->header->wsa__MessageID);

  /* Check ReplyTo has Address */
  if (!soap->header->wsa__ReplyTo || !soap->header->wsa__ReplyTo->Address)
    return soap_sender_fault(soap, "No WS-Addressing ReplyTo address", NULL);
  /* Copy Header info into response Header */
  soap->header->wsa__To = soap->header->wsa__ReplyTo->Address;

  /* Add info to response Header */
  soap->header->wsa__MessageID = soap_strdup(soap, soap_int2s(soap, id_count++));
  soap->header->wsa__Action = "http://genivia.com/udp/echoStringResponse";

  /* Copy request string into response string */
  printf("Response message %s returned\n", soap->header->wsa__MessageID);
  *res = str;

  return SOAP_OK;
}

int ns__sendString(struct soap *soap, char *str)
{ if (check_header(soap))
    printf("Malformed header\n");
  else if (check_received(soap->header->wsa__MessageID))
    printf("One-way message %s already received\n", soap->header->wsa__MessageID);
  else
    printf("One-way message %s accepted and serviced\n", soap->header->wsa__MessageID);
  return SOAP_OK;
}
