/*
  The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
  Copyright (C) 2001,2002,2003  Aymeric MOIZARD jack@atosc.org
  
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  
  This library 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
  Lesser General Public License for more details.
  
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

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

#include <osipparser2/osip_rfc3264.h>
#include <osipparser2/osip_port.h>

#define AUDIO_CODEC 0x01
#define VIDEO_CODEC 0x02
#define T38_CODEC   0x04
#define APP_CODEC   0x08

int test_add_codec (struct osip_rfc3264 *cnf, int codec_type,
                    int payload, char *attribute);
sdp_message_t *get_test_remote_message (int index, FILE * torture_file,
                                        int verbose);

int
test_add_codec (struct osip_rfc3264 *cnf, int codec_type,
                int payload, char *attribute)
{
  sdp_media_t *med;
  sdp_attribute_t *attr;
  char *tmp;
  int i;

  if (payload > 127)
    return -1;
  if (attribute == NULL || strlen (attribute) == 0)
    return -1;

  i = sdp_media_init (&med);
  if (i != 0)
    goto error;

  tmp = malloc (4);
  snprintf (tmp, 3, "%i", payload);
  med->m_proto = strdup ("RTP/AVP");
  osip_list_add (med->m_payloads, tmp, -1);

  i = sdp_attribute_init (&attr);
  if (i != 0)
    return -1;
  attr->a_att_field = strdup ("rtpmap");
  attr->a_att_value = strdup (attribute);
  osip_list_add (med->a_attributes, attr, -1);


  switch (codec_type)
    {
      case AUDIO_CODEC:
        med->m_media = strdup ("audio");
        osip_rfc3264_add_audio_media (cnf, med, -1);
        break;
      case VIDEO_CODEC:
        med->m_media = strdup ("video");
        osip_rfc3264_add_video_media (cnf, med, -1);
        break;
    }

  return 0;

error:
  return -1;
}

sdp_message_t *
get_test_remote_message (int index, FILE * torture_file, int verbose)
{
  sdp_message_t *remote_sdp;
  char *msg;
  char *tmpmsg;
  char *tmp;
  char *marker;
  int i;

  i = 0;
  tmp = (char *) osip_malloc (500);
  marker = fgets (tmp, 500, torture_file);      /* lines are under 500 */
  while (marker != NULL && i < index)
    {
      if (0 == strncmp (tmp, "|", 1))
        i++;
      marker = fgets (tmp, 500, torture_file);
    }

  msg = (char *) osip_malloc (10000);   /* msg are under 10000 */
  tmpmsg = msg;

  if (marker == NULL)
    {
      fprintf (stderr,
               "Error! The message's number you specified does not exist\n");
      osip_free (msg);
      return NULL;              /* end of file detected! */
    }
  /* this part reads an entire message, separator is "|" */
  /* (it is unlinkely that it will appear in messages!) */
  while (marker != NULL && strncmp (tmp, "|", 1))
    {
      osip_strncpy (tmpmsg, tmp, strlen (tmp));
      tmpmsg = tmpmsg + strlen (tmp);
      marker = fgets (tmp, 500, torture_file);
    }

  if (verbose)
    fprintf (stdout, "%s\n", msg);

  i = sdp_message_init (&remote_sdp);
  if (i != 0)
    return NULL;

  i = sdp_message_parse (remote_sdp, msg);
  if (i != 0)
    return NULL;

  return remote_sdp;
}

int
main (int argc, char **argv)
{
  struct osip_rfc3264 *cnf;
  int i;
  int verbose = 0;              /* 0: verbose, 1 (or nothing: not verbose) */
  FILE *torture_file;

  if (argc > 3)
    {
      if (0 == strncmp (argv[3], "-v", 2))
        verbose = 1;
      if (0 == strcmp (argv[3], "-vv"))
        verbose = 2;
    }

  fprintf (stdout, "test %i : ============================ \n", atoi (argv[2]));

  torture_file = fopen (argv[1], "r");
  if (torture_file == NULL)
    {
      fprintf (stderr,
               "Failed to open \"torture_sdps\" file.\nUsage: %s torture_file [-v]\n",
               argv[0]);
      fprintf (stdout, "test %s : ============================ FAILED\n", argv[2]);
      exit (1);
    }






  i = osip_rfc3264_init (&cnf);
  if (i != 0)
    {
      fprintf (stderr, "Cannot Initialize Negotiator feature.\n");
      osip_rfc3264_free (cnf);
      fclose (torture_file);
      fprintf (stdout, "test %s : ============================ FAILED\n", argv[2]);
      return -1;
    }

  test_add_codec (cnf, AUDIO_CODEC, 0, "0 PCMU/8000");
  test_add_codec (cnf, AUDIO_CODEC, 8, "8 PCMA/8000");
  test_add_codec (cnf, AUDIO_CODEC, 18, "18 G729/8000");

  test_add_codec (cnf, VIDEO_CODEC, 97, "97 XXX/11111");
  test_add_codec (cnf, VIDEO_CODEC, 31, "31 H261/90000");

#if 0
  osip_rfc3264_del_video_media (cnf, 0);
  osip_rfc3264_del_audio_media (cnf, 1);
  osip_rfc3264_del_audio_media (cnf, 2);

  test_add_codec (cnf, AUDIO_CODEC, 8, "0 PCMA/8000");
  test_add_codec (cnf, AUDIO_CODEC, 18, "18 G729/8000");
#endif

  if (verbose == 2)
    __osip_rfc3264_print_codecs (cnf);

  {
    sdp_message_t *remote_sdp;
    sdp_media_t *audio_tab[10];
    sdp_media_t *video_tab[10];
    sdp_media_t *t38_tab[10];
    sdp_media_t *app_tab[10];
    int res_audio = 0;
    int res_video = 0;
    int res_t38 = 0;
    int res_app = 0;

    char str_local_sdp[8192];
    sdp_message_t *local_sdp;
    int mline;
    char *tmp = NULL;

    remote_sdp = get_test_remote_message (atoi (argv[2]), torture_file, verbose);
    if (!remote_sdp)
      {
        fprintf (stderr, "Cannot Get remote SDP message for testing.\n");
        osip_rfc3264_free (cnf);
        fclose (torture_file);
        fprintf (stdout, "test %s : ============================ FAILED\n",
                 argv[2]);
        return -1;
      }

    i = osip_rfc3264_prepare_answer (cnf, remote_sdp, str_local_sdp, 8192);
    if (i != 0)
      {
        fprintf (stderr, "Cannot Prepare local SDP answer from offer.\n");
        osip_rfc3264_free (cnf);
        fclose (torture_file);
        fprintf (stdout, "test %s : ============================ FAILED\n",
                 argv[2]);
        return -1;
      }
    sdp_message_init (&local_sdp);
    i = sdp_message_parse (local_sdp, str_local_sdp);
    if (i != 0)
      {
        fprintf (stderr, "Cannot Parse uncomplete SDP answer from offer.\n");
        sdp_message_free (local_sdp);
        osip_rfc3264_free (cnf);
        fclose (torture_file);
        fprintf (stdout, "test %s : ============================ FAILED\n",
                 argv[2]);
        return -1;
      }

    mline = 0;
    while (0 == osip_rfc3264_match (cnf, remote_sdp,
                                    audio_tab, video_tab, t38_tab, app_tab, mline))
      {
        int pos;

        if (audio_tab[0] == NULL && video_tab[0] == NULL && t38_tab[0] == NULL
            && app_tab[0] == NULL)
          {
            if (verbose)
              fprintf (stdout,
                       "The remote SDP does not match any local payloads.\n");
        } else
          {
            for (pos = 0; audio_tab[pos] != NULL; pos++)
              {
                int pos2 = 0;
                sdp_media_t *med = audio_tab[pos];
                char *str = (char *) osip_list_get (med->m_payloads, 0);

                if (verbose == 2)
                  fprintf (stdout, "\tm=%s %s %s %s\n",
                           med->m_media, med->m_port, med->m_proto, str);
                while (!osip_list_eol (med->a_attributes, pos2))
                  {
                    sdp_attribute_t *attr =
                      (sdp_attribute_t *) osip_list_get (med->a_attributes,
                                                         pos2);

                    if (verbose == 2)
                      fprintf (stdout, "\ta=%s:%s\n",
                               attr->a_att_field, attr->a_att_value);
                    pos2++;
                  }
                if (verbose == 2)
                  fprintf (stdout, "\n");

                i =
                  osip_rfc3264_complete_answer (cnf, remote_sdp, local_sdp,
                                                audio_tab[pos], mline);
                if (i != 0)
                  {
                    if (verbose)
                      fprintf (stdout,
                               "Error Adding support for codec in answer?\n");
                } else
                  {
                    if (verbose == 2)
                      fprintf (stdout, "support for codec added in answer:\n");
                  }
              }

            for (pos = 0; video_tab[pos] != NULL; pos++)
              {
                int pos2 = 0;
                sdp_media_t *med = video_tab[pos];
                char *str = (char *) osip_list_get (med->m_payloads, 0);

                if (verbose == 2)
                  fprintf (stdout, "\tm=%s %s %s %s\n",
                           med->m_media, med->m_port, med->m_proto, str);
                while (!osip_list_eol (med->a_attributes, pos2))
                  {
                    sdp_attribute_t *attr =
                      (sdp_attribute_t *) osip_list_get (med->a_attributes,
                                                         pos2);

                    if (verbose == 2)
                      fprintf (stdout, "\ta=%s:%s\n",
                               attr->a_att_field, attr->a_att_value);
                    pos2++;
                  }
                if (verbose == 2)
                  fprintf (stdout, "\n");

                i =
                  osip_rfc3264_complete_answer (cnf, remote_sdp, local_sdp,
                                                video_tab[pos], mline);
                if (i != 0)
                  {
                    if (verbose)
                      fprintf (stdout,
                               "Error Adding support for codec in answer?\n");
                } else
                  {
                    if (verbose == 2)
                      fprintf (stdout, "support for codec added in answer:\n");
                  }
              }
          }

        mline++;
      }

    if (verbose)
      fprintf (stdout, "Result in answer:\n");
    sdp_message_to_str (local_sdp, &tmp);
    if (tmp != NULL)
      {
        if (verbose)
          fprintf (stdout, "\n%s\n", tmp);
        free (tmp);
    } else
      {
        if (verbose)
          fprintf (stdout, "ERROR\n");
      }
  }

  osip_rfc3264_free (cnf);
  fclose (torture_file);
  fprintf (stdout, "test %s : ============================ OK\n", argv[2]);
  return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1