Logo Search packages:      
Sourcecode: wengophone version File versions  Download package

jresponse.c

/*
  eXosip - This is the eXtended osip library.
  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
  
  eXosip 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.
  
  eXosip 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
*/


#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif

#include "eXosip2.h"
#include <eXosip/eXosip_cfg.h>

extern eXosip_t eXosip;

/* Private functions */
static char *generating_no_sdp_answer(eXosip_call_t *jc, eXosip_dialog_t *jd,
                   osip_message_t *orig_request, char *local_sdp_port, char *local_video_port);

int
eXosip_build_response_default(int jid, int status)
{
  return -1;
}

int
_eXosip_build_response_default(osip_message_t **dest, osip_dialog_t *dialog,
                         int status, osip_message_t *request)
{
  osip_generic_param_t *tag;
  osip_message_t *response;
  int pos;
  int i;

  if (request==NULL) return -1;

  i = osip_message_init(&response);
  if (i!=0)
    return -1;
  /* initialise osip_message_t structure */
  /* yet done... */

  response->sip_version = (char *)osip_malloc(8*sizeof(char));
  sprintf(response->sip_version,"SIP/2.0");
  osip_message_set_status_code(response, status);

  /* handle some internal reason definitions. */
  if (MSG_IS_NOTIFY(request) && status==481)
    {
      response->reason_phrase = osip_strdup("Subcription Does Not Exist");
    }
  else if (MSG_IS_SUBSCRIBE(request) && status==202)
    {
      response->reason_phrase = osip_strdup("Accepted subscription");
    }
  else
    {
      response->reason_phrase = osip_strdup(osip_message_get_reason(status));
      if (response->reason_phrase==NULL)
      {
        if (response->status_code == 101)
          response->reason_phrase = osip_strdup("Dialog Establishement");
        else
          response->reason_phrase = osip_strdup("Unknown code");
      }
      response->req_uri     = NULL;
      response->sip_method = NULL;
    }

  i = osip_to_clone(request->to, &(response->to));
  if (i!=0) goto grd_error_1;

  i = osip_to_get_tag(response->to,&tag);
  if (i!=0)
    {  /* we only add a tag if it does not already contains one! */
      if ((dialog!=NULL) && (dialog->local_tag!=NULL))
      /* it should contain the local TAG we created */
      { osip_to_set_tag(response->to, osip_strdup(dialog->local_tag)); }
      else
      {
        if (status!=100)
          osip_to_set_tag(response->to, osip_to_tag_new_random());
      }
    }

  i = osip_from_clone(request->from, &(response->from));
  if (i!=0) goto grd_error_1;

  pos = 0;
  while (!osip_list_eol(request->vias,pos))
    {
      osip_via_t *via;
      osip_via_t *via2;
      via = (osip_via_t *)osip_list_get(request->vias,pos);
      i = osip_via_clone(via, &via2);
      if (i!=-0) goto grd_error_1;
      osip_list_add(response->vias, via2, -1);
      pos++;
    }

  i = osip_call_id_clone(request->call_id, &(response->call_id));
  if (i!=0) goto grd_error_1;
  i = osip_cseq_clone(request->cseq, &(response->cseq));
  if (i!=0) goto grd_error_1;

  if (MSG_IS_SUBSCRIBE(request))
    {
      osip_header_t *exp;
      osip_message_set_header(response, "Event", "presence");
      i = osip_message_get_expires(request, 0, &exp);
      if (exp==NULL)
      {
        osip_header_t *cp;
        i = osip_header_clone(exp, &cp);
        if (cp!=NULL)
          osip_list_add(response->headers, cp, 0);
      }
    }
    
  osip_message_set_allow(response, "INVITE");
  osip_message_set_allow(response, "ACK");
  osip_message_set_allow(response, "OPTIONS");
  osip_message_set_allow(response, "CANCEL");
  osip_message_set_allow(response, "BYE");
  osip_message_set_allow(response, "SUBSCRIBE");
  osip_message_set_allow(response, "NOTIFY");
  osip_message_set_allow(response, "MESSAGE");
  osip_message_set_allow(response, "INFO");
  osip_message_set_allow(response, "REFER");

  *dest = response;
  return 0;

 grd_error_1:
  osip_message_free(response);
  return -1;
}

int
complete_answer_that_establish_a_dialog2(osip_message_t *response, osip_message_t *request, char *ctct)
{
  int i;
  int pos=0;
  char contact[1000];
#ifdef SM
  char *locip=NULL;
#else
  char locip[50];
#endif
  /* 12.1.1:
     copy all record-route in response
     add a contact with global scope
  */
  while (!osip_list_eol(request->record_routes, pos))
    {
      osip_record_route_t *rr;
      osip_record_route_t *rr2;
      rr = osip_list_get(request->record_routes, pos);
      i = osip_record_route_clone(rr, &rr2);
      if (i!=0) return -1;
      osip_list_add(response->record_routes, rr2, -1);
      pos++;
    }

#ifdef SM
  eXosip_get_localip_from_via(response,&locip);
#else
  eXosip_guess_ip_for_via(eXosip.ip_family, locip, 49);
#endif
  
  if (ctct && ctct[0])
    snprintf(contact,1000, "%s", ctct);
  else if (eXosip.answer_contact[0])
    snprintf(contact,1000, "%s", eXosip.answer_contact);
  else if (request->to->url->username==NULL)
    snprintf(contact,1000, "<sip:%s:%s>", locip, eXosip.localport);
  else
    snprintf(contact,1000, "<sip:%s@%s:%s>", request->to->url->username,
           locip, eXosip.localport);

  if (eXosip.j_firewall_ip[0]!='\0')
    {
      osip_contact_t *con = (osip_contact_t *) osip_list_get (request->contacts, 0);
      if (con!=NULL && con->url!=NULL && con->url->host!=NULL)
      {
        char *c_address = con->url->host;

        struct addrinfo *addrinfo;
        struct __eXosip_sockaddr addr;
        i = eXosip_get_addrinfo(&addrinfo, con->url->host, 5060);
        if (i==0)
            {
              memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
              freeaddrinfo (addrinfo);
              c_address = inet_ntoa (((struct sockaddr_in *) &addr)->sin_addr);
              OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_INFO1, NULL,
                    "eXosip: here is the resolved destination host=%s\n", c_address));
            }

        /* If c_address is a PUBLIC address, the request was
           coming from the PUBLIC network. */
        if (eXosip_is_public_address(c_address))
          {
            if (request->to->url->username==NULL)
            snprintf(contact,1000, "<sip:%s:%s>", eXosip.j_firewall_ip,
                   eXosip.localport);
            else
            snprintf(contact,1000, "<sip:%s@%s:%s>", request->to->url->username,
                   eXosip.j_firewall_ip, eXosip.localport);
          }
      }
    }

#ifdef SM
  osip_free(locip);
#endif

  osip_message_set_contact(response, contact);
      
  return 0;
}

int
complete_answer_that_establish_a_dialog(osip_message_t *response, osip_message_t *request)
{
  complete_answer_that_establish_a_dialog2(response, request, 0);
}

static char *
generating_no_sdp_answer(eXosip_call_t *jc, eXosip_dialog_t *jd,
                   osip_message_t *orig_request, char *local_sdp_port, char *local_video_port)
{
  sdp_message_t *local_sdp = NULL;
  char *local_body = NULL;
  char *size;
  int i;
  
  jc->c_ack_sdp = 1;
  if(osip_negotiation_sdp_build_offer(eXosip.osip_negotiation, NULL, &local_sdp, local_sdp_port, local_video_port) != 0)
    return NULL;
  
  if (local_sdp!=NULL)
    {
      int pos=0;
      while (!sdp_message_endof_media (local_sdp, pos))
      {
        int k = 0;
        char *tmp = sdp_message_m_media_get (local_sdp, pos);
        if (0 == strncmp (tmp, "audio", 5))
          {
            char *payload = NULL;
            do {
            payload = sdp_message_m_payload_get (local_sdp, pos, k);
            if (payload == NULL)
              {
              }
            else if (0==strcmp("110",payload))
              {
                sdp_message_a_attribute_add (local_sdp,
                                     pos,
                                     osip_strdup ("AS"),
                                     osip_strdup ("110 20"));
              }
            else if (0==strcmp("111",payload))
              {
                sdp_message_a_attribute_add (local_sdp,
                                     pos,
                                     osip_strdup ("AS"),
                                     osip_strdup ("111 20"));
              }
            k++;
            } while (payload != NULL);
          }
        pos++;
      }
    }
  
  i = sdp_message_to_str(local_sdp, &local_body);
  
  if (local_body!=NULL)
    {
      size= (char *)osip_malloc(7*sizeof(char));
#ifdef __APPLE_CC__
      sprintf(size,"%li",strlen(local_body));
#else
      sprintf(size,"%i",strlen(local_body));
#endif
      osip_message_set_content_length(orig_request, size);
      osip_free(size);
  
      osip_message_set_body(orig_request, local_body, strlen(local_body));
      osip_message_set_content_type(orig_request, "application/sdp");
    }
  else
    osip_message_set_content_length(orig_request, "0");
  
  osip_negotiation_ctx_set_local_sdp(jc->c_ctx, local_sdp);
  
  OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO3,NULL,"200 OK w/ SDP (RESPONSE TO INVITE w/ NO SDP)=\n%s\n", local_body));
  
  return local_body;
}

char *
generating_sdp_answer(osip_message_t *request, osip_negotiation_ctx_t *context)
{
  sdp_message_t *remote_sdp;
  sdp_message_t *local_sdp = NULL;
  int i;
  char *local_body;
  if (context==NULL)
    return NULL;

  local_body = NULL;
  if (MSG_IS_INVITE(request)||MSG_IS_OPTIONS(request)||MSG_IS_RESPONSE_FOR(request, "INVITE"))
    {
      osip_body_t *body;
      body = (osip_body_t *)osip_list_get(request->bodies,0);
      if(body == NULL)
      return NULL;
      
      /* remote_sdp = (sdp_message_t *) osip_malloc(sizeof(sdp_message_t)); */
      i = sdp_message_init(&remote_sdp);
      if (i!=0) return NULL;
      
      /* WE ASSUME IT IS A SDP BODY AND THAT    */
      /* IT IS THE ONLY ONE, OF COURSE, THIS IS */
      /* NOT TRUE */
      i = sdp_message_parse(remote_sdp,body->body);
      if (i!=0) return NULL;

      i = osip_negotiation_ctx_set_remote_sdp(context, remote_sdp);

      i = osip_negotiation_ctx_execute_negotiation(eXosip.osip_negotiation, context);
      if (i==200)
      {
        local_sdp = osip_negotiation_ctx_get_local_sdp(context);

        if (eXosip.j_firewall_ip[0]!='\0')
        {
              char *c_address = NULL;
              int pos=0;
              /* If remote message contains a Public IP, we have to replace the SDP
                  connection address */
              c_address = sdp_message_c_addr_get(remote_sdp, -1, 0);
              while (c_address==NULL)
              {
                    c_address = sdp_message_c_addr_get(remote_sdp, pos, 0);
                    pos++;
                    if (pos>10)
                          break;
              }
              if (c_address!=NULL) /* found a connection address: check if it is public */
              {

                    struct addrinfo *addrinfo;
                    struct __eXosip_sockaddr addr;
                    i = eXosip_get_addrinfo(&addrinfo, c_address, 5060);
                    if (i==0)
                        {
                          memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
                          freeaddrinfo (addrinfo);
                          c_address = inet_ntoa (((struct sockaddr_in *) &addr)->sin_addr);
                          OSIP_TRACE (osip_trace
                                (__FILE__, __LINE__, OSIP_INFO1, NULL,
                                "eXosip: here is the resolved destination host=%s\n", c_address));
                        }

                    if (eXosip_is_public_address(c_address))
                      {
                          /* replace the IP with our firewall ip */
                          sdp_connection_t *conn;
                          pos=-1;
                          conn = sdp_message_connection_get(local_sdp, pos, 0);
                          while (conn!=NULL)
                          {
                                if (conn->c_addr!=NULL )
                                {
                                      osip_free(conn->c_addr);
                                      conn->c_addr = osip_strdup(eXosip.j_firewall_ip);
                                }
                                pos++;
                                conn = sdp_message_connection_get(local_sdp, pos, 0);
                          }
                      }
              }
        }

        i = sdp_message_to_str(local_sdp, &local_body);

        remote_sdp = osip_negotiation_ctx_get_remote_sdp(context);
        sdp_message_free(remote_sdp);
        osip_negotiation_ctx_set_remote_sdp(context, NULL);

        if (i!=0) {
          OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_ERROR,NULL,"ERROR: Could not parse local SDP answer %i\n",i));
          return NULL;
        }
        return local_body;
      }
      else if (i==415)
      {
        OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,"WARNING: Unsupported media %i\n",i));
      }
      else
      {
        OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_ERROR,NULL,"ERROR: while building answer to SDP (%i)\n",i));
      }
      remote_sdp = osip_negotiation_ctx_get_remote_sdp(context);
      sdp_message_free(remote_sdp);
      osip_negotiation_ctx_set_remote_sdp(context, NULL);
    }
  return NULL;
}

int
eXosip_answer_options_1xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code)
{
  osip_event_t *evt_answer;
  osip_transaction_t *tr;
  osip_message_t *response;
  int i;

  tr = eXosip_find_last_inc_options(jc, jd);
  if (tr==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer"));
      return -1;
    }

  if (jd!=NULL)
    {
      i = _eXosip_build_response_default(&response, jd->d_dialog, code, tr->orig_request);
    }
  else
    {
      i = _eXosip_build_response_default(&response, NULL, code, tr->orig_request);
    }

  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_ERROR,NULL,"ERROR: Could not create response for OPTIONS\n"));
      return -1;
    }

  evt_answer = osip_new_outgoing_sipmessage(response);
  evt_answer->transactionid = tr->transactionid;

  osip_transaction_add_event(tr, evt_answer);
  __eXosip_wakeup();
  return 0;
}

int
eXosip_answer_options_2xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code)
{
  osip_event_t *evt_answer;
  osip_transaction_t *tr;
  osip_message_t *response;
  sdp_message_t *sdp;
  char *body;
  char size[10];
  int i;

  tr = eXosip_find_last_inc_options(jc, jd);
  if (tr==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer"));
      return -1;
    }
  osip_negotiation_sdp_build_offer(eXosip.osip_negotiation, NULL, &sdp, "10400", NULL);
  if (sdp==NULL)
    {
      return -1;
    }
  if (jd!=NULL)
    {
      i = _eXosip_build_response_default(&response, jd->d_dialog, code, tr->orig_request);
    }
  else
    {
      i = _eXosip_build_response_default(&response, NULL, code, tr->orig_request);
    }
  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,"ERROR: Could not create response for options\n"));
      sdp_message_free(sdp); /* not used */
      return -1;
    }
  i = sdp_message_to_str(sdp, &body);
  sdp_message_free(sdp);
  if (i!=0) {
    osip_message_free(response);
    return -1;
  }
  i = osip_message_set_body(response, body, strlen(body));
  if (i!=0) {
    osip_message_free(response);
    return -1;
  }
#ifdef __APPLE_CC__
  snprintf(size, 9,"%li",strlen(body));
#else
  snprintf(size, 9,"%i",strlen(body));
#endif
  i = osip_message_set_content_length(response, size);
  if (i!=0) {
    osip_free(body);
    osip_message_free(response);
    return -1;
  }
  osip_free(body);
  i = osip_message_set_content_type(response, "application/sdp");
  if (i!=0) {
    osip_message_free(response);
    return -1;
  }

  evt_answer = osip_new_outgoing_sipmessage(response);
  evt_answer->transactionid = tr->transactionid;

  osip_transaction_add_event(tr, evt_answer);
  __eXosip_wakeup();
  return 0;
}

int
eXosip_answer_options_3456xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code)
{
  osip_event_t *evt_answer;
  osip_transaction_t *tr;
  osip_message_t *response;
  int i;
  tr = eXosip_find_last_inc_options(jc, jd);
  if (tr==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer"));
      return -1;
    }

  if (jd!=NULL)
    {
      i = _eXosip_build_response_default(&response, jd->d_dialog, code, tr->orig_request);
    }
  else
    {
      i = _eXosip_build_response_default(&response, NULL, code, tr->orig_request);
    }
  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,"ERROR: Could not create response for options\n"));
      return -1;
    }

  if (300<=code<=399)
    {
      /* Should add contact fields */
      /* ... */
    }

  osip_message_set_content_length(response, "0");
  /*  send message to transaction layer */

  evt_answer = osip_new_outgoing_sipmessage(response);
  evt_answer->transactionid = tr->transactionid;

  osip_transaction_add_event(tr, evt_answer);
  __eXosip_wakeup();

  return 0;
}

int
_eXosip2_answer_invite_1xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code, osip_message_t **answer)
{
  int i;
  osip_transaction_t *tr;
  tr = eXosip_find_last_inc_invite(jc, jd);
  if (tr==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer"));
      return -1;
    }
  /* is the transaction already answered? */
  if (tr->state==IST_COMPLETED
      || tr->state==IST_CONFIRMED
      || tr->state==IST_TERMINATED)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: transaction already answered\n"));
      return -1;
    }

  if (jd==NULL)
    i = _eXosip_build_response_default(answer, NULL, code, tr->orig_request);
  else
    i = _eXosip_build_response_default(answer, jd->d_dialog, code, tr->orig_request);

  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_ERROR,NULL,"ERROR: Could not create response for invite\n"));
      return -2;
    }

  osip_message_set_content_length(*answer, "0");
  /*  send message to transaction layer */

  if (code>100)
    {
      i = complete_answer_that_establish_a_dialog(*answer, tr->orig_request);
    }
  
  return 0;
}

int
_eXosip2_answer_invite_2xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code, osip_message_t **answer)
{
  int i;
  osip_transaction_t *tr;
  tr = eXosip_find_last_inc_invite(jc, jd);

  if (tr==NULL || tr->orig_request==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer\n"));
      return -1;
    }

  if (jd!=NULL && jd->d_dialog==NULL)
    {  /* element previously removed */
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot answer this closed transaction\n"));
      return -1;
    }

  /* is the transaction already answered? */
  if (tr->state==IST_COMPLETED
      || tr->state==IST_CONFIRMED
      || tr->state==IST_TERMINATED)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: transaction already answered\n"));
      return -1;
    }
  
  if (jd==NULL)
    i = _eXosip_build_response_default(answer, NULL, code, tr->orig_request);
  else
    i = _eXosip_build_response_default(answer, jd->d_dialog, code, tr->orig_request);

  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,"ERROR: Could not create response for invite\n"));
      return -1;
    }

  /* request that estabish a dialog: */
  /* 12.1.1 UAS Behavior */
  {
    i = complete_answer_that_establish_a_dialog(*answer, tr->orig_request);
    if (i!=0) goto g2atii_error_1;; /* ?? */
  }

  return 0;

 g2atii_error_1:
  osip_message_free(*answer);
  return -1;
}

int
_eXosip2_answer_invite_3456xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code, osip_message_t **answer)
{
  int i;
  osip_transaction_t *tr;
  tr = eXosip_find_last_inc_invite(jc, jd);
  if (tr==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer"));
      return -1;
    }
  /* is the transaction already answered? */
  if (tr->state==IST_COMPLETED
      || tr->state==IST_CONFIRMED
      || tr->state==IST_TERMINATED)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: transaction already answered\n"));
      return -1;
    }

  i = _eXosip_build_response_default(answer, jd->d_dialog, code, tr->orig_request);
  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,"ERROR: Could not create response for invite\n"));
      return -1;
    }

  if (300<=code<=399)
    {
      /* Should add contact fields */
      /* ... */
    }

  osip_message_set_content_length(*answer, "0");
  /*  send message to transaction layer */

  return 0;
}

int
eXosip_answer_invite_1xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code, char *ctct)
{
  osip_event_t *evt_answer;
  osip_message_t *response;
  int i;
  osip_transaction_t *tr;
  tr = eXosip_find_last_inc_invite(jc, jd);
  if (tr==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer"));
      return -1;
    }
  /* is the transaction already answered? */
  if (tr->state==IST_COMPLETED
      || tr->state==IST_CONFIRMED
      || tr->state==IST_TERMINATED)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: transaction already answered\n"));
      return -1;
    }

  if (jd==NULL)
    i = _eXosip_build_response_default(&response, NULL, code, tr->orig_request);
  else
    i = _eXosip_build_response_default(&response, jd->d_dialog, code, tr->orig_request);

  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_ERROR,NULL,"ERROR: Could not create response for invite\n"));
      return -2;
    }

  osip_message_set_content_length(response, "0");
  /*  send message to transaction layer */

  if (code>100)
    {
      /* request that estabish a dialog: */
      /* 12.1.1 UAS Behavior */
      i = complete_answer_that_establish_a_dialog2(response, tr->orig_request, ctct);

      if (jd==NULL)
      {
        i = eXosip_dialog_init_as_uas(&jd, tr->orig_request, response);
        if (i!=0)
          {
         OSIP_TRACE (osip_trace
                 (__FILE__, __LINE__, OSIP_ERROR, NULL,
               "eXosip: cannot create dialog!\n"));
          }
        ADD_ELEMENT(jc->c_dialogs, jd);
      }
    }

  evt_answer = osip_new_outgoing_sipmessage(response);
  evt_answer->transactionid = tr->transactionid;

  osip_transaction_add_event(tr, evt_answer);
  __eXosip_wakeup();
  
  return 0;
}

int
eXosip_answer_invite_2xx_with_body(eXosip_call_t *jc, eXosip_dialog_t *jd, int code,const char*bodytype, const char*body)
{
  osip_event_t *evt_answer;
  osip_message_t *response;
  int i;
  char *size;
  osip_transaction_t *tr;
  tr = eXosip_find_last_inc_invite(jc, jd);

  if (tr==NULL || tr->orig_request==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer\n"));
      return -1;
    }

  if (jd!=NULL && jd->d_dialog==NULL)
    {  /* element previously removed */
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot answer this closed transaction\n"));
      return -1;
    }

  /* is the transaction already answered? */
  if (tr->state==IST_COMPLETED
      || tr->state==IST_CONFIRMED
      || tr->state==IST_TERMINATED)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: transaction already answered\n"));
      return -1;
    }
  
  if (jd==NULL)
    i = _eXosip_build_response_default(&response, NULL, code, tr->orig_request);
  else
    i = _eXosip_build_response_default(&response, jd->d_dialog, code, tr->orig_request);

  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,"ERROR: Could not create response for invite\n"));
      code = 500; /* ? which code to use? */
      return -1;
    }

  if (code==488)
    {
      osip_message_set_content_length(response, "0");
      /*  TODO: send message to transaction layer */
      evt_answer = osip_new_outgoing_sipmessage(response);
      evt_answer->transactionid = tr->transactionid;
      osip_transaction_add_event(tr, evt_answer);
  __eXosip_wakeup();
      return 0;
    }

  i = osip_message_set_body(response, body, strlen(body));
  if (i!=0) {
    goto g2atii_error_1;
  }
  size = (char *) osip_malloc(6*sizeof(char));
  sprintf(size,"%i",strlen(body));
  i = osip_message_set_content_length(response, size);
  osip_free(size);
  if (i!=0) goto g2atii_error_1;
  i = osip_message_set_header(response, "content-type", bodytype);
  if (i!=0) goto g2atii_error_1;

  /* request that estabish a dialog: */
  /* 12.1.1 UAS Behavior */
  {
    i = complete_answer_that_establish_a_dialog(response, tr->orig_request);
    if (i!=0) goto g2atii_error_1;; /* ?? */
  }
  /* THIS RESPONSE MUST BE SENT RELIABILY until the final ACK is received !! */
  /* this response must be stored at the upper layer!!! (it will be destroyed*/
  /* right after being sent! */

  if (jd==NULL)
    {
      i = eXosip_dialog_init_as_uas(&jd, tr->orig_request, response);
      if (i!=0)
      {
     OSIP_TRACE (osip_trace
             (__FILE__, __LINE__, OSIP_ERROR, NULL,
           "eXosip: cannot create dialog!\n"));
        return -1;
      }
      ADD_ELEMENT(jc->c_dialogs, jd);
    }

  eXosip_dialog_set_200ok(jd, response);
  evt_answer = osip_new_outgoing_sipmessage(response);
  evt_answer->transactionid = tr->transactionid;

  osip_transaction_add_event(tr, evt_answer);

  osip_dialog_set_state(jd->d_dialog, DIALOG_CONFIRMED);
  __eXosip_wakeup();
  return 0;

 g2atii_error_1:
  osip_message_free(response);
  return -1;
}

int
eXosip_answer_invite_2xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code, char *local_sdp_port, char *ctct, char *local_video_port)
{
  osip_event_t *evt_answer;
  osip_message_t *response;
  int i;
  char *size;
  char *body = NULL;
  osip_transaction_t *tr;
  tr = eXosip_find_last_inc_invite(jc, jd);

  if (tr==NULL || tr->orig_request==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer\n"));
      return -1;
    }

  if (jd!=NULL && jd->d_dialog==NULL)
    {  /* element previously removed */
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot answer this closed transaction\n"));
      return -1;
    }

  /* is the transaction already answered? */
  if (tr->state==IST_COMPLETED
      || tr->state==IST_CONFIRMED
      || tr->state==IST_TERMINATED)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: transaction already answered\n"));
      return -1;
    }

  /* WE SHOULD LOOK FOR A SDP PACKET!! */
  if(NULL != osip_list_get(tr->orig_request->bodies,0))
    {
      body = generating_sdp_answer(tr->orig_request, jc->c_ctx);
      if (body==NULL)
      code = 488; /* bad sdp */
    }
  else
    {
      if(local_sdp_port==NULL && local_video_port == NULL)
      code = 488; /* session description in the request is not acceptable. */
      else
      /* body is NULL (contains no SDP), generate a response to INVITE w/ no SDP */
      body = generating_no_sdp_answer(jc, jd, tr->orig_request, local_sdp_port, local_video_port);
    }
  
  if (jd==NULL)
    i = _eXosip_build_response_default(&response, NULL, code, tr->orig_request);
  else
    i = _eXosip_build_response_default(&response, jd->d_dialog, code, tr->orig_request);

  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,"ERROR: Could not create response for invite\n"));
      code = 500; /* ? which code to use? */
      osip_free(body); /* not used */
      return -1;
    }

  if (code==488)
    {
      osip_message_set_content_length(response, "0");
      /*  TODO: send message to transaction layer */
      osip_free(body);
      evt_answer = osip_new_outgoing_sipmessage(response);
      evt_answer->transactionid = tr->transactionid;
      osip_transaction_add_event(tr, evt_answer);
        __eXosip_wakeup();
      return 0;
    }

  i = osip_message_set_body(response, body, strlen(body));
  if (i!=0) {
    goto g2atii_error_1;
  }
  size = (char *) osip_malloc(6*sizeof(char));
#ifdef __APPLE_CC__
  sprintf(size,"%li",strlen(body));
#else
  sprintf(size,"%i",strlen(body));
#endif
  i = osip_message_set_content_length(response, size);
  osip_free(size);
  if (i!=0) goto g2atii_error_1;
  i = osip_message_set_content_type(response, "application/sdp");
  if (i!=0) goto g2atii_error_1;

  /* request that estabish a dialog: */
  /* 12.1.1 UAS Behavior */
  {
    i = complete_answer_that_establish_a_dialog2(response, tr->orig_request, ctct);
    if (i!=0) goto g2atii_error_1;; /* ?? */
  }

  osip_free(body);
  /* THIS RESPONSE MUST BE SENT RELIABILY until the final ACK is received !! */
  /* this response must be stored at the upper layer!!! (it will be destroyed*/
  /* right after being sent! */

  if (jd==NULL)
    {
      i = eXosip_dialog_init_as_uas(&jd, tr->orig_request, response);
      if (i!=0)
      {
     OSIP_TRACE (osip_trace
             (__FILE__, __LINE__, OSIP_ERROR, NULL,
           "eXosip: cannot create dialog!\n"));
        return -1;
      }
      ADD_ELEMENT(jc->c_dialogs, jd);
    }

  eXosip_dialog_set_200ok(jd, response);
  evt_answer = osip_new_outgoing_sipmessage(response);
  evt_answer->transactionid = tr->transactionid;

  osip_transaction_add_event(tr, evt_answer);

  osip_dialog_set_state(jd->d_dialog, DIALOG_CONFIRMED);
  __eXosip_wakeup();
  return 0;

 g2atii_error_1:
  osip_free(body);
  osip_message_free(response);
  return -1;
}

int
eXosip_answer_invite_3456xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code, const char *contact)
{
  osip_event_t *evt_answer;
  osip_message_t *response;
  int i;
  osip_transaction_t *tr;
  tr = eXosip_find_last_inc_invite(jc, jd);
  if (tr==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer"));
      return -1;
    }
  /* is the transaction already answered? */
  if (tr->state==IST_COMPLETED
      || tr->state==IST_CONFIRMED
      || tr->state==IST_TERMINATED)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: transaction already answered\n"));
      return -1;
    }

  i = _eXosip_build_response_default(&response, jd->d_dialog, code, tr->orig_request);
  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,"ERROR: Could not create response for invite\n"));
      return -1;
    }

  if (300<=code<=399 && (contact != 0))
    {
      osip_message_clean_contacts(response);
      osip_message_set_contact(response, contact);
    }

  osip_message_set_content_length(response, "0");
  /*  send message to transaction layer */

  evt_answer = osip_new_outgoing_sipmessage(response);
  evt_answer->transactionid = tr->transactionid;

  osip_transaction_add_event(tr, evt_answer);
  __eXosip_wakeup();
  return 0;
}


void
eXosip_notify_answer_subscribe_1xx(eXosip_notify_t *jn, eXosip_dialog_t *jd, int code)
{
  osip_event_t *evt_answer;
  osip_message_t *response;
  int i;
  osip_transaction_t *tr;
  tr = eXosip_find_last_inc_subscribe(jn, jd);
  if (tr==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer"));
      return;
    }

  if (jd==NULL)
    i = _eXosip_build_response_default(&response, NULL, code, tr->orig_request);
  else
    i = _eXosip_build_response_default(&response, jd->d_dialog, code, tr->orig_request);

  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_ERROR,NULL,"ERROR: Could not create response for subscribe\n"));
      return;
    }

  if (code>100)
    {
      /* request that estabish a dialog: */
      /* 12.1.1 UAS Behavior */
      i = complete_answer_that_establish_a_dialog(response, tr->orig_request);

      if (jd==NULL)
      {
        i = eXosip_dialog_init_as_uas(&jd, tr->orig_request, response);
        if (i!=0)
          {
         OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
               "eXosip: cannot create dialog!\n"));
          }
        ADD_ELEMENT(jn->n_dialogs, jd);
      }
    }

  evt_answer = osip_new_outgoing_sipmessage(response);
  evt_answer->transactionid = tr->transactionid;

  osip_transaction_add_event(tr, evt_answer);
  __eXosip_wakeup();
  return ;
}

void
eXosip_notify_answer_subscribe_2xx(eXosip_notify_t *jn, eXosip_dialog_t *jd, int code)
{
  osip_event_t *evt_answer;
  osip_message_t *response;
  int i;
  osip_transaction_t *tr;
  tr = eXosip_find_last_inc_subscribe(jn, jd);

  if (tr==NULL || tr->orig_request==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer\n"));
      return;
    }

  if (jd!=NULL && jd->d_dialog==NULL)
    {  /* element previously removed, this is a no hop! */
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot answer this closed transaction\n"));
      return ;
    }

  if (jd==NULL)
    i = _eXosip_build_response_default(&response, NULL, code, tr->orig_request);
  else
    i = _eXosip_build_response_default(&response, jd->d_dialog, code, tr->orig_request);

  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,"ERROR: Could not create response for subscribe\n"));
      code = 500; /* ? which code to use? */
      return;
    }

  /* request that estabish a dialog: */
  /* 12.1.1 UAS Behavior */
  {
    i = complete_answer_that_establish_a_dialog(response, tr->orig_request);
    if (i!=0) goto g2atii_error_1;; /* ?? */
  }

  /* THIS RESPONSE MUST BE SENT RELIABILY until the final ACK is received !! */
  /* this response must be stored at the upper layer!!! (it will be destroyed*/
  /* right after being sent! */

  if (jd==NULL)
    {
      i = eXosip_dialog_init_as_uas(&jd, tr->orig_request, response);
      if (i!=0)
      {
     OSIP_TRACE (osip_trace
       (__FILE__, __LINE__, OSIP_ERROR, NULL,
           "eXosip: cannot create dialog!\n"));
        return;
      }
      ADD_ELEMENT(jn->n_dialogs, jd);
    }

  eXosip_dialog_set_200ok(jd, response);
  evt_answer = osip_new_outgoing_sipmessage(response);
  evt_answer->transactionid = tr->transactionid;

  osip_transaction_add_event(tr, evt_answer);
  __eXosip_wakeup();

  osip_dialog_set_state(jd->d_dialog, DIALOG_CONFIRMED);
  return ;

 g2atii_error_1:
  osip_message_free(response);
  return ;
}

void
eXosip_notify_answer_subscribe_3456xx(eXosip_notify_t *jn, eXosip_dialog_t *jd, int code)
{
  osip_event_t *evt_answer;
  osip_message_t *response;
  int i;
  osip_transaction_t *tr;
  tr = eXosip_find_last_inc_subscribe(jn, jd);
  if (tr==NULL)
    {
      OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
         "eXosip: cannot find transaction to answer"));
      return;
    }
  i = _eXosip_build_response_default(&response, jd->d_dialog, code, tr->orig_request);
  if (i!=0)
    {
      OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,"ERROR: Could not create response for subscribe\n"));
      return;
    }

  if (300<=code<=399)
    {
      /* Should add contact fields */
      /* ... */
    }

  evt_answer = osip_new_outgoing_sipmessage(response);
  evt_answer->transactionid = tr->transactionid;

  osip_transaction_add_event(tr, evt_answer);
  __eXosip_wakeup();
  return ;
}

Generated by  Doxygen 1.6.0   Back to index