예제 #1
0
int
eXosip_call_terminate (int cid, int did)
{
  int i;
  osip_transaction_t *tr;
  osip_message_t *request = NULL;
  eXosip_dialog_t *jd = NULL;
  eXosip_call_t *jc = NULL;

  if (did <= 0 && cid <= 0)
    return OSIP_BADPARAMETER;
  if (did > 0)
    {
      eXosip_call_dialog_find (did, &jc, &jd);
      if (jd == NULL)
        {
          OSIP_TRACE (osip_trace
                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
                       "eXosip: No call here?\n"));
          return OSIP_NOTFOUND;
        }
  } else
    {
      eXosip_call_find (cid, &jc);
    }

  if (jc == NULL)
    {
      return OSIP_NOTFOUND;
    }

  tr = eXosip_find_last_out_invite (jc, jd);
  if (jd != NULL && jd->d_dialog != NULL
      && jd->d_dialog->state == DIALOG_CONFIRMED)
    {
      /* don't send CANCEL on re-INVITE: send BYE instead */
  } else if (tr != NULL && tr->last_response != NULL
             && MSG_IS_STATUS_1XX (tr->last_response))
    {
      i = generating_cancel (&request, tr->orig_request);
      if (i != 0)
        {
          OSIP_TRACE (osip_trace
                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
                       "eXosip: cannot terminate this call!\n"));
          return i;
        }
      i = eXosip_create_cancel_transaction (jc, jd, request);
      if (i != 0)
        {
          OSIP_TRACE (osip_trace
                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
                       "eXosip: cannot initiate SIP transaction!\n"));
          return i;
        }
      if (jd != NULL)
        {
          osip_dialog_free (jd->d_dialog);
          jd->d_dialog = NULL;
          eXosip_update ();     /* AMD 30/09/05 */
        }
      return OSIP_SUCCESS;
    }

  if (jd == NULL || jd->d_dialog == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: No established dialog!\n"));
      return OSIP_WRONG_STATE;
    }

  if (tr == NULL)
    {
      /*this may not be enough if it's a re-INVITE! */
      tr = eXosip_find_last_inc_invite (jc, jd);
      if (tr != NULL && tr->last_response != NULL &&
          MSG_IS_STATUS_1XX (tr->last_response))
        {                       /* answer with 603 */
          osip_generic_param_t *to_tag;
          osip_from_param_get_byname (tr->orig_request->to, "tag", &to_tag);

          i = eXosip_call_send_answer (tr->transactionid, 603, NULL);

          if (to_tag == NULL)
            return i;
        }
    }

  if (jd->d_dialog == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: cannot terminate this call!\n"));
      return OSIP_WRONG_STATE;
    }

  i = generating_bye (&request, jd->d_dialog, eXosip.transport);

  if (i != 0)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: cannot terminate this call!\n"));
      return i;
    }

  eXosip_add_authentication_information (request, NULL);

  i = eXosip_create_transaction (jc, jd, request);
  if (i != 0)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: cannot initiate SIP transaction!\n"));
      return i;
    }

  osip_dialog_free (jd->d_dialog);
  jd->d_dialog = NULL;
  eXosip_update ();             /* AMD 30/09/05 */
  return OSIP_SUCCESS;
}
예제 #2
0
static int
_eXosip_retry_with_auth (eXosip_dialog_t * jd, osip_transaction_t ** ptr,
                         int *retry)
{
  osip_transaction_t *out_tr = NULL;
  osip_transaction_t *tr = NULL;
  osip_message_t *msg = NULL;
  osip_event_t *sipevent;
  jinfo_t *ji = NULL;

  int cseq;
  osip_via_t *via;
  int i;

  if (!ptr)
    return -1;

  if (jd != NULL)
    {
      if (jd->d_out_trs == NULL)
        return -1;
    }

  out_tr = *ptr;

  if (out_tr == NULL
      || out_tr->orig_request == NULL || out_tr->last_response == NULL)
    return -1;

  if (retry && (*retry >= 3))
    return -1;

  osip_message_clone (out_tr->orig_request, &msg);
  if (msg == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: could not clone msg for authentication\n"));
      return -1;
    }

  via = (osip_via_t *) osip_list_get (&msg->vias, 0);
  if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL)
    {
      osip_message_free (msg);
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: missing via or cseq header\n"));
      return -1;
    }

  /* increment cseq */
  cseq = atoi (msg->cseq->number);
  osip_free (msg->cseq->number);
  msg->cseq->number = strdup_printf ("%i", cseq + 1);
  if (jd != NULL && jd->d_dialog != NULL)
    {
      jd->d_dialog->local_cseq++;
    }

  i = eXosip_update_top_via(msg);
  if (i!=0)
    {
      osip_message_free (msg);
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: unsupported protocol\n"));
      return -1;
    }

  if (eXosip_add_authentication_information (msg, out_tr->last_response) < 0)
    {
      osip_message_free (msg);
      return -1;
    }

  osip_message_force_update (msg);

  if (MSG_IS_INVITE (msg))
    i = _eXosip_transaction_init (&tr, ICT, eXosip.j_osip, msg);
  else
    i = _eXosip_transaction_init (&tr, NICT, eXosip.j_osip, msg);

  if (i != 0)
    {
      osip_message_free (msg);
      return -1;
    }

  /* replace with the new tr */
  if (MSG_IS_PUBLISH(msg))
    {
      /* old transaction is put in the garbage list */
      osip_list_add (eXosip.j_transactions, out_tr, 0);
      /* new transaction is put in the publish context */
      *ptr = tr;
    }
  else
    osip_list_add (eXosip.j_transactions, tr, 0);

  sipevent = osip_new_outgoing_sipmessage (msg);

  ji = osip_transaction_get_your_instance (out_tr);

  osip_transaction_set_your_instance (out_tr, NULL);
  osip_transaction_set_your_instance (tr, ji);
  osip_transaction_add_event (tr, sipevent);

  if (retry)
    (*retry)++;

  eXosip_update ();             /* fixed? */
  __eXosip_wakeup ();
  return 0;
}
예제 #3
0
int
_eXosip_call_retry_request (eXosip_call_t * jc,
                            eXosip_dialog_t * jd, osip_transaction_t * out_tr)
{
  osip_transaction_t *tr = NULL;
  osip_message_t *msg = NULL;
  osip_event_t *sipevent;

  int cseq;
  osip_via_t *via;
  osip_contact_t *co;
  int pos;
  int i;
  int protocol = IPPROTO_UDP;

  if (jc == NULL)
    return OSIP_BADPARAMETER;
  if (jd != NULL)
    {
      if (jd->d_out_trs == NULL)
        return OSIP_BADPARAMETER;
    }
  if (out_tr == NULL
      || out_tr->orig_request == NULL || out_tr->last_response == NULL)
    return OSIP_BADPARAMETER;

  i = osip_message_clone (out_tr->orig_request, &msg);
  if (i != 0)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: could not clone msg for authentication\n"));
      return i;
    }

  via = (osip_via_t *) osip_list_get (&msg->vias, 0);
  if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL)
    {
      osip_message_free (msg);
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: missing via or cseq header\n"));
      return OSIP_SYNTAXERROR;
    }

  if (MSG_IS_STATUS_3XX (out_tr->last_response))
    {
      co = NULL;
      pos = 0;
      while (!osip_list_eol (&out_tr->last_response->contacts, pos))
        {
          co =
            (osip_contact_t *) osip_list_get (&out_tr->last_response->contacts,
                                              pos);
          if (co != NULL && co->url != NULL)
            {
              /* check tranport? Only allow UDP, right now */
              osip_uri_param_t *u_param;
              int pos2;

              u_param = NULL;
              pos2 = 0;
              while (!osip_list_eol (&co->url->url_params, pos2))
                {
                  u_param =
                    (osip_uri_param_t *) osip_list_get (&co->url->url_params,
                                                        pos2);
                  if (u_param == NULL || u_param->gname == NULL
                      || u_param->gvalue == NULL)
                    {
                      u_param = NULL;
                      /* skip */
                  } else if (0 == osip_strcasecmp (u_param->gname, "transport"))
                    {
                      if (0 == osip_strcasecmp (u_param->gvalue, "udp"))
                        {
                          u_param = NULL;
                          protocol = IPPROTO_UDP;
                          break;        /* ok */
                      } else if (0 == osip_strcasecmp (u_param->gvalue, "tcp"))
                        {
                          protocol = IPPROTO_TCP;
                          u_param = NULL;
                        }
                      break;
                    }
                  pos2++;
                }

              if (u_param == NULL || u_param->gname == NULL
                  || u_param->gvalue == NULL)
                {
                  break;        /* default is udp! */
                }
            }
          pos++;
          co = NULL;
        }

      if (co == NULL || co->url == NULL)
        {
          osip_message_free (msg);
          OSIP_TRACE (osip_trace
                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
                       "eXosip: contact header\n"));
          return OSIP_SYNTAXERROR;
        }

      /* TODO:
         remove extra parameter from new request-uri
         check usual parameter like "transport"
       */

      if (msg->req_uri != NULL && msg->req_uri->host != NULL
          && co->url->host != NULL
          && 0 == osip_strcasecmp (co->url->host, msg->req_uri->host))
        {
          osip_uri_param_t *maddr_param = NULL;
          osip_uri_uparam_get_byname (co->url, "maddr", &maddr_param);
          if (maddr_param != NULL && maddr_param->gvalue != NULL)
            {
              /* This is a redirect server, the route should probably be removed? */
              osip_route_t *route = NULL;
              osip_generic_param_t *tag = NULL;
              osip_message_get_route (msg, 0, &route);
              if (route != NULL)
                {
                  osip_to_get_tag (msg->to, &tag);
                  if (tag == NULL && route != NULL && route->url != NULL)
                    {
                      osip_list_remove (&msg->routes, 0);
                      osip_route_free (route);
                    }
                }
            }
        }

      /* replace request-uri with NEW contact address */
      osip_uri_free (msg->req_uri);
      msg->req_uri = NULL;
      osip_uri_clone (co->url, &msg->req_uri);

      /* support for diversions headers/draft! */
      {
        int count = 0;
        pos = 0;
        while (!osip_list_eol (&out_tr->last_response->headers, pos))
          {
            osip_header_t *copy = NULL;
            osip_header_t *head =
              osip_list_get (&out_tr->last_response->headers, pos);
            if (head != NULL && 0 == osip_strcasecmp (head->hname, "diversion"))
              {
                i = osip_header_clone (head, &copy);
                if (i == 0)
                  {
                    osip_list_add (&msg->headers, copy, count);
                    count++;
                  }
              }
            pos++;
          }
      }

    }
  /* remove all previous authentication headers */
  osip_list_special_free (&msg->authorizations,
                          (void *(*)(void *)) &osip_authorization_free);
  osip_list_special_free (&msg->proxy_authorizations,
                          (void *(*)(void *)) &osip_proxy_authorization_free);

  /* increment cseq */
  cseq = atoi (msg->cseq->number);
  osip_free (msg->cseq->number);
  msg->cseq->number = strdup_printf ("%i", cseq + 1);
  if (jd != NULL && jd->d_dialog != NULL)
    {
      jd->d_dialog->local_cseq++;
    }

  i = eXosip_update_top_via (msg);
  if (i != 0)
    {
      osip_message_free (msg);
      return i;
    }

  if (out_tr->last_response->status_code == 401
      || out_tr->last_response->status_code == 407)
    eXosip_add_authentication_information (msg, out_tr->last_response);
  else
    eXosip_add_authentication_information (msg, NULL);
  osip_message_force_update (msg);

  if (0 != osip_strcasecmp (msg->sip_method, "INVITE"))
    {
      i = _eXosip_transaction_init (&tr, NICT, eXosip.j_osip, msg);
  } else
    {
      i = _eXosip_transaction_init (&tr, ICT, eXosip.j_osip, msg);
    }

  if (i != 0)
    {
      osip_message_free (msg);
      return i;
    }

  if (out_tr == jc->c_out_tr)
    {
      /* replace with the new tr */
      osip_list_add (&eXosip.j_transactions, jc->c_out_tr, 0);
      jc->c_out_tr = tr;

      /* fix dialog issue */
      if (jd != NULL)
        {
          REMOVE_ELEMENT (jc->c_dialogs, jd);
          eXosip_dialog_free (jd);
          jd = NULL;
        }
  } else
    {
      /* add the new tr for the current dialog */
      osip_list_add (jd->d_out_trs, tr, 0);
    }

  sipevent = osip_new_outgoing_sipmessage (msg);

#ifndef MINISIZE
  osip_transaction_set_your_instance (tr, __eXosip_new_jinfo (jc, jd, NULL, NULL));
#else
  osip_transaction_set_your_instance (tr, __eXosip_new_jinfo (jc, jd));
#endif
  osip_transaction_add_event (tr, sipevent);

  eXosip_update ();             /* fixed? */
  __eXosip_wakeup ();
  return OSIP_SUCCESS;
}
예제 #4
0
int
eXosip_call_build_request (int jid, const char *method, osip_message_t ** request)
{
  eXosip_dialog_t *jd = NULL;
  eXosip_call_t *jc = NULL;

  osip_transaction_t *transaction;
  int i;

  *request = NULL;
  if (jid <= 0)
    return OSIP_BADPARAMETER;
  if (method == NULL || method[0] == '\0')
    return OSIP_BADPARAMETER;

  if (jid > 0)
    {
      eXosip_call_dialog_find (jid, &jc, &jd);
    }
  if (jd == NULL || jd->d_dialog == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: No call here?\n"));
      return OSIP_NOTFOUND;
    }

  transaction = NULL;
  if (0 == osip_strcasecmp (method, "INVITE"))
    {
      transaction = eXosip_find_last_invite (jc, jd);
  } else                        /* OPTIONS, UPDATE, INFO, REFER, ?... */
    {
      transaction = eXosip_find_last_transaction (jc, jd, method);
    }

  if (transaction != NULL)
    {
      if (0 != osip_strcasecmp (method, "INVITE"))
        {
          if (transaction->state != NICT_TERMINATED &&
              transaction->state != NIST_TERMINATED &&
              transaction->state != NICT_COMPLETED &&
              transaction->state != NIST_COMPLETED)
            return OSIP_WRONG_STATE;
      } else
        {
          if (transaction->state != ICT_TERMINATED &&
              transaction->state != IST_TERMINATED &&
              transaction->state != IST_CONFIRMED &&
              transaction->state != ICT_COMPLETED)
            return OSIP_WRONG_STATE;
        }
    }

  i = _eXosip_build_request_within_dialog (request, method, jd->d_dialog,
                                           eXosip.transport);
  if (i != 0)
    return i;

  eXosip_add_authentication_information (*request, NULL);

  return OSIP_SUCCESS;
}
예제 #5
0
int
_eXosip_insubscription_send_request_with_credential (eXosip_notify_t * jn,
        eXosip_dialog_t * jd,
        osip_transaction_t * out_tr)
{
    osip_transaction_t *tr = NULL;
    osip_message_t *msg = NULL;
    osip_event_t *sipevent;

    char locip[256];
    int cseq;
    char tmp[256];
    osip_via_t *via;
    int i;

    if (jn == NULL)
        return -1;
    if (jd != NULL)
    {
        if (jd->d_out_trs == NULL)
            return -1;
    }

    if (out_tr == NULL)
    {
        out_tr = eXosip_find_last_out_notify (jn, jd);
    }

    if (out_tr == NULL
            || out_tr->orig_request == NULL || out_tr->last_response == NULL)
        return -1;

    osip_message_clone (out_tr->orig_request, &msg);
    if (msg == NULL)
    {
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_ERROR, NULL,
                     "eXosip: could not clone msg for authentication\n"));
        return -1;
    }

    via = (osip_via_t *) osip_list_get (msg->vias, 0);
    if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL)
    {
        osip_message_free (msg);
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_ERROR, NULL,
                     "eXosip: missing via or cseq header\n"));
        return -1;
    }

    /* increment cseq */
    cseq = atoi (msg->cseq->number);
    osip_free (msg->cseq->number);
    msg->cseq->number = strdup_printf ("%i", cseq + 1);
    if (jd != NULL && jd->d_dialog != NULL)
    {
        jd->d_dialog->local_cseq++;
    }

    osip_list_remove (msg->vias, 0);
    osip_via_free (via);

    i = _eXosip_find_protocol (out_tr->orig_request);
    if (i == IPPROTO_UDP)
    {
        eXosip_guess_ip_for_via (eXosip.net_interfaces[0].net_ip_family, locip,
                                 sizeof (locip));
        if (eXosip.net_interfaces[0].net_ip_family == AF_INET6)
            snprintf (tmp, 256, "SIP/2.0/UDP [%s]:%s;branch=z9hG4bK%u",
                      locip, eXosip.net_interfaces[0].net_port,
                      via_branch_new_random ());
        else
            snprintf (tmp, 256, "SIP/2.0/UDP %s:%s;rport;branch=z9hG4bK%u",
                      locip, eXosip.net_interfaces[0].net_port,
                      via_branch_new_random ());
    } else if (i == IPPROTO_TCP)
    {
        eXosip_guess_ip_for_via (eXosip.net_interfaces[1].net_ip_family, locip,
                                 sizeof (locip));
        if (eXosip.net_interfaces[1].net_ip_family == AF_INET6)
            snprintf (tmp, 256, "SIP/2.0/TCP [%s]:%s;branch=z9hG4bK%u",
                      locip, eXosip.net_interfaces[1].net_port,
                      via_branch_new_random ());
        else
            snprintf (tmp, 256, "SIP/2.0/TCP %s:%s;rport;branch=z9hG4bK%u",
                      locip, eXosip.net_interfaces[1].net_port,
                      via_branch_new_random ());
    } else
    {
        /* tls? */
        osip_message_free (msg);
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_ERROR, NULL,
                     "eXosip: unsupported protocol\n"));
        return -1;
    }

    osip_via_init (&via);
    osip_via_parse (via, tmp);
    osip_list_add (msg->vias, via, 0);

    eXosip_add_authentication_information (msg, out_tr->last_response);
    osip_message_force_update (msg);

    i = osip_transaction_init (&tr, NICT, eXosip.j_osip, msg);

    if (i != 0)
    {
        osip_message_free (msg);
        return -1;
    }

    /* add the new tr for the current dialog */
    osip_list_add (jd->d_out_trs, tr, 0);

    sipevent = osip_new_outgoing_sipmessage (msg);

    osip_transaction_set_your_instance (tr, __eXosip_new_jinfo (NULL, jd, NULL, jn));
    osip_transaction_add_event (tr, sipevent);

    eXosip_update ();             /* fixed? */
    __eXosip_wakeup ();
    return 0;
}
예제 #6
0
static int
_eXosip_register_build_register (eXosip_reg_t * jr, osip_message_t ** _reg)
{
    osip_message_t *reg = NULL;
    int i;

    reg = NULL;
    *_reg = NULL;

    if (jr->r_last_tr != NULL)
    {
        if (jr->r_last_tr->state != NICT_TERMINATED
                && jr->r_last_tr->state != NICT_COMPLETED)
            return -1;
        else
        {
            osip_message_t *last_response = NULL;
            osip_transaction_t *tr;

            osip_message_clone (jr->r_last_tr->orig_request, &reg);
            if (reg == NULL)
                return -1;
            /* reg = jr->r_last_tr->orig_request; */
            if (jr->r_last_tr->last_response != NULL)
            {
                osip_message_clone (jr->r_last_tr->last_response, &last_response);
                if (last_response == NULL)
                {
                    osip_message_free (reg);
                    return -1;
                }
            }

            __eXosip_delete_jinfo (jr->r_last_tr);
            tr = jr->r_last_tr;
            jr->r_last_tr = NULL;
            osip_list_add (eXosip.j_transactions, tr, 0);

            /* modify the REGISTER request */
            {
                int osip_cseq_num = osip_atoi (reg->cseq->number);
                int length = strlen (reg->cseq->number);


                osip_list_special_free(&reg->authorizations, (void *(*)(void *)) &osip_authorization_free);
                osip_list_special_free(&reg->proxy_authorizations, (void *(*)(void *)) &osip_proxy_authorization_free);


                if (-1 == eXosip_update_top_via (reg))
                {
                    osip_message_free (reg);
                    if (last_response != NULL)
                        osip_message_free (last_response);
                    return -1;
                }

                osip_cseq_num++;
                osip_free (reg->cseq->number);
                reg->cseq->number = (char *) osip_malloc (length + 2);      /* +2 like for 9 to 10 */
                sprintf (reg->cseq->number, "%i", osip_cseq_num);

                {
                    osip_header_t *exp;

                    osip_message_header_get_byname (reg, "expires", 0, &exp);
                    if (exp!=NULL)
                    {
                        if (exp->hvalue!=NULL)
                            osip_free (exp->hvalue);
                        exp->hvalue = (char *) osip_malloc (10);
                        snprintf (exp->hvalue, 9, "%i", jr->r_reg_period);
                    }
                }

                osip_message_force_update (reg);
            }

            if (last_response != NULL)
            {
                if (last_response->status_code==401 || last_response->status_code==407)
                {
                    eXosip_add_authentication_information (reg, last_response);
                }
                else
                    eXosip_add_authentication_information (reg, NULL);
                osip_message_free (last_response);
            }
        }
    }
    if (reg == NULL)
    {
        i = generating_register (jr, &reg, eXosip.transport,
                                 jr->r_aor, jr->r_registrar, jr->r_contact,
                                 jr->r_reg_period);
        if (i != 0)
        {
            return -2;
        }
    }

    *_reg = reg;
    return 0;
}
예제 #7
0
static int
_eXosip_register_build_register(eXosip_reg_t * jr, osip_message_t ** _reg)
{
	osip_message_t *reg = NULL;
	int i;

	*_reg = NULL;

	if (jr == NULL)
		return OSIP_BADPARAMETER;

	if (jr->r_last_tr != NULL) {
		if (jr->r_last_tr->state != NICT_TERMINATED
			&& jr->r_last_tr->state != NICT_COMPLETED)
			return OSIP_WRONG_STATE;
		else {
			osip_message_t *last_response = NULL;
			osip_transaction_t *tr;

			i = osip_message_clone(jr->r_last_tr->orig_request, &reg);
			if (i != 0)
				return i;
			if (jr->r_last_tr->last_response != NULL) {
				i = osip_message_clone(jr->r_last_tr->last_response,
									   &last_response);
				if (i != 0) {
					osip_message_free(reg);
					return i;
				}
			}

			__eXosip_delete_jinfo(jr->r_last_tr);
			tr = jr->r_last_tr;
			jr->r_last_tr = NULL;
			osip_list_add(&eXosip.j_transactions, tr, 0);

			/* modify the REGISTER request */
			{
				int osip_cseq_num = osip_atoi(reg->cseq->number);
				int length = strlen(reg->cseq->number);


				osip_list_special_free(&reg->authorizations, (void (*)(void *))
									   &osip_authorization_free);
				osip_list_special_free(&reg->proxy_authorizations,
									   (void (*)(void *))
									   &osip_proxy_authorization_free);


				i = eXosip_update_top_via(reg);
				if (i != 0) {
					osip_message_free(reg);
					if (last_response != NULL)
						osip_message_free(last_response);
					return i;
				}

				osip_cseq_num++;
				osip_free(reg->cseq->number);
				reg->cseq->number = (char *) osip_malloc(length + 2);	/* +2 like for 9 to 10 */
				if (reg->cseq->number == NULL) {
					osip_message_free(reg);
					if (last_response != NULL)
						osip_message_free(last_response);
					return OSIP_NOMEM;
				}
				snprintf(reg->cseq->number, length + 2, "%i", osip_cseq_num);


				if (last_response != NULL && last_response->status_code == 423) {
					/* increase expires value to "min-expires" value */
					osip_header_t *exp;
					osip_header_t *min_exp;

					osip_message_header_get_byname(reg, "expires", 0, &exp);
					osip_message_header_get_byname(last_response, "min-expires", 0,
												   &min_exp);
					if (exp != NULL && exp->hvalue != NULL && min_exp != NULL
						&& min_exp->hvalue != NULL) {
						osip_free(exp->hvalue);
						exp->hvalue = osip_strdup(min_exp->hvalue);
						jr->r_reg_period = atoi(min_exp->hvalue);
					} else {
						osip_message_free(reg);
						if (last_response != NULL)
							osip_message_free(last_response);
						OSIP_TRACE(osip_trace
								   (__FILE__, __LINE__, OSIP_ERROR, NULL,
									"eXosip: missing Min-Expires or Expires in REGISTER\n"));
						return OSIP_SYNTAXERROR;
					}
				} else {
					osip_header_t *exp;

					osip_message_header_get_byname(reg, "expires", 0, &exp);
					if (exp != NULL) {
						if (exp->hvalue != NULL)
							osip_free(exp->hvalue);
						exp->hvalue = (char *) osip_malloc(10);
						if (exp->hvalue == NULL) {
							osip_message_free(reg);
							if (last_response != NULL)
								osip_message_free(last_response);
							return OSIP_NOMEM;
						}
						snprintf(exp->hvalue, 9, "%i", jr->r_reg_period);
					}
				}

				osip_message_force_update(reg);
			}

			if (last_response != NULL) {
				if (last_response->status_code == 401
					|| last_response->status_code == 407) {
					eXosip_add_authentication_information(reg, last_response);
				} else
					eXosip_add_authentication_information(reg, NULL);
				osip_message_free(last_response);
			}
		}
	}
	if (reg == NULL) {
		i = generating_register(jr, &reg, eXosip.transport,
								jr->r_aor, jr->r_registrar, jr->r_contact,
								jr->r_reg_period);
		if (i != 0)
			return i;
	}

	*_reg = reg;
	return OSIP_SUCCESS;
}
예제 #8
0
int eXosip_reinvite_with_authentication (struct eXosip_call_t *jc)
{
    struct eXosip_call_t *jcc;
#ifdef SM

    char *locip;
#else
    char locip[50];
#endif
	osip_message_t * cloneinvite;
  	osip_event_t *sipevent;
  	osip_transaction_t *transaction;
	int osip_cseq_num,length;
    osip_via_t *via;
    char *tmp;
    int i;

	osip_message_clone (jc->c_out_tr->orig_request, &cloneinvite);

	osip_cseq_num = osip_atoi(jc->c_out_tr->orig_request->cseq->number);
	length   = strlen(jc->c_out_tr->orig_request->cseq->number);
	tmp    = (char *)osip_malloc(90*sizeof(char));
	via   = (osip_via_t *) osip_list_get (cloneinvite->vias, 0);

	osip_list_remove(cloneinvite->vias, 0);
	osip_via_free(via);

#ifdef SM
	eXosip_get_localip_for(cloneinvite->req_uri->host,&locip);
#else
	eXosip_guess_ip_for_via(eXosip.ip_family, locip, 49);
#endif

	if (eXosip.ip_family==AF_INET6) {
		sprintf(tmp, "SIP/2.0/UDP [%s]:%s;branch=z9hG4bK%u", locip,
		      eXosip.localport, via_branch_new_random());
	} else {
		sprintf(tmp, "SIP/2.0/UDP %s:%s;branch=z9hG4bK%u", locip,
		      eXosip.localport, via_branch_new_random());
	}
#ifdef SM
	osip_free(locip);
#endif
	osip_via_init(&via);
	osip_via_parse(via, tmp);
	osip_list_add(cloneinvite->vias, via, 0);
	osip_free(tmp);

	osip_cseq_num++;
	osip_free(cloneinvite->cseq->number);
	cloneinvite->cseq->number = (char*)osip_malloc(length + 2);
	sprintf(cloneinvite->cseq->number, "%i", osip_cseq_num);

	eXosip_add_authentication_information(cloneinvite, jc->c_out_tr->last_response);
    cloneinvite->message_property = 0;

    eXosip_call_init(&jcc);
    i = osip_transaction_init(&transaction,
		       ICT,
		       eXosip.j_osip,
		       cloneinvite);
    if (i!=0)
    {
      eXosip_call_free(jc);
      osip_message_free(cloneinvite);
      return -1;
    }
    jcc->c_out_tr = transaction;
    sipevent = osip_new_outgoing_sipmessage(cloneinvite);
    sipevent->transactionid =  transaction->transactionid;
    osip_transaction_set_your_instance(transaction, __eXosip_new_jinfo(jcc,
NULL, NULL, NULL));
    osip_transaction_add_event(transaction, sipevent);

    jcc->external_reference = 0;
    ADD_ELEMENT(eXosip.j_calls, jcc);

    eXosip_update(); /* fixed? */
    __eXosip_wakeup();
	return 0;
}
int
_eXosip_insubscription_send_request_with_credential (eXosip_notify_t * jn,
                                                     eXosip_dialog_t * jd,
                                                     osip_transaction_t * out_tr)
{
  osip_transaction_t *tr = NULL;
  osip_message_t *msg = NULL;
  osip_event_t *sipevent;

  int cseq;
  osip_via_t *via;
  int i;

  if (jn == NULL)
    return OSIP_BADPARAMETER;
  if (jd != NULL)
    {
      if (jd->d_out_trs == NULL)
        return OSIP_BADPARAMETER;
    }

  if (out_tr == NULL)
    {
      out_tr = eXosip_find_last_out_notify (jn, jd);
    }

  if (out_tr == NULL
      || out_tr->orig_request == NULL || out_tr->last_response == NULL)
    return OSIP_NOTFOUND;

  i = osip_message_clone (out_tr->orig_request, &msg);
  if (i != 0)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: could not clone msg for authentication\n"));
      return i;
    }

  via = (osip_via_t *) osip_list_get (&msg->vias, 0);
  if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL)
    {
      osip_message_free (msg);
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: missing via or cseq header\n"));
      return OSIP_SYNTAXERROR;
    }

  /* increment cseq */
  cseq = atoi (msg->cseq->number);
  osip_free (msg->cseq->number);
  msg->cseq->number = strdup_printf ("%i", cseq + 1);
  if (msg->cseq->number == NULL)
    {
      osip_message_free (msg);
      return OSIP_NOMEM;
    }

  if (jd != NULL && jd->d_dialog != NULL)
    {
      jd->d_dialog->local_cseq++;
    }

  i = eXosip_update_top_via (msg);
  if (i != 0)
    {
      osip_message_free (msg);
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: unsupported protocol\n"));
      return i;
    }

  if (out_tr->last_response->status_code == 401
      || out_tr->last_response->status_code == 407)
    eXosip_add_authentication_information (msg, out_tr->last_response);
  else
    eXosip_add_authentication_information (msg, NULL);

  osip_message_force_update (msg);

  i = _eXosip_transaction_init (&tr, NICT, eXosip.j_osip, msg);

  if (i != 0)
    {
      osip_message_free (msg);
      return i;
    }

  /* add the new tr for the current dialog */
  osip_list_add (jd->d_out_trs, tr, 0);

  sipevent = osip_new_outgoing_sipmessage (msg);

  osip_transaction_set_your_instance (tr, __eXosip_new_jinfo (NULL, jd, NULL, jn));
  osip_transaction_add_event (tr, sipevent);

  eXosip_update ();             /* fixed? */
  __eXosip_wakeup ();
  return OSIP_SUCCESS;
}