linphone-developers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Linphone-developers] bug in eXosip_process_response_out_of_transaction(


From: Машкин С В
Subject: [Linphone-developers] bug in eXosip_process_response_out_of_transaction(), eXosip2/udp.c
Date: Thu, 24 Sep 2009 09:48:30 +0400

Hi, Simon!
We have found little bug in eXosip2/udp.c function
eXosip_process_response_out_of_transaction (osip_event_t * evt)
Removed-bug-source is below:

The bug was in call of cb_snd_message (NULL, bye, NULL, 0, -1);
with bye=NULL. The check (bye==NULL) was absent, so, at
some conditions our system fall with "NULL pointer access" error.

Bug area marked with //<<<<<<<, //>>>>>>>

===============================================
static void
eXosip_process_response_out_of_transaction (osip_event_t * evt)
{
  eXosip_call_t *jc = NULL;
  eXosip_dialog_t *jd = NULL;
  time_t now;

  now = time (NULL);
  if (evt->sip == NULL
      || evt->sip->cseq == NULL
      || evt->sip->cseq->number == NULL
      || evt->sip->to == NULL || evt->sip->from == NULL)
    {
      osip_event_free (evt);
      return;
    }

  /* search for existing dialog: match branch & to tag */
  for (jc = eXosip.j_calls; jc != NULL; jc = jc->next)
    {
      /* search for calls with only ONE outgoing transaction */
      if (jc->c_id >= 1 && jc->c_dialogs != NULL && jc->c_out_tr != NULL)
        {
          for (jd = jc->c_dialogs; jd != NULL; jd = jd->next)
            {
              /* only initial request are concerned with this */
              if (jd->d_id >= 1 && jd->d_dialog != NULL)
                {
                  /* match answer with dialog */
                  osip_generic_param_t *tag;

                  osip_from_get_tag (evt->sip->to, &tag);

                  if (jd->d_dialog->remote_tag == NULL || tag == NULL)
                    continue;
                  if (jd->d_dialog->remote_tag != NULL && tag != NULL
                      && tag->gvalue != NULL
                      && 0 == strcmp (jd->d_dialog->remote_tag, tag->gvalue))
                    break;
                }
            }
          if (jd != NULL)
            break;              /* found a matching dialog! */

          /* check if the transaction match this from tag */
          if (jc->c_out_tr->orig_request != NULL
              && jc->c_out_tr->orig_request->from != NULL)
            {
              osip_generic_param_t *tag_invite;
              osip_generic_param_t *tag;
              osip_from_get_tag (jc->c_out_tr->orig_request->from, &tag_invite);
              osip_from_get_tag (evt->sip->from, &tag);

              if (tag_invite == NULL || tag == NULL)
                continue;
              if (tag_invite->gvalue != NULL && tag->gvalue != NULL
                  && 0 == strcmp (tag_invite->gvalue, tag->gvalue))
                break;
            }
        }
    }

  if (jc == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
                   "Incoming 2xx has no relations with current calls: Message 
discarded.\r\n"));
      osip_event_free (evt);
      return;
    }
#ifndef MINISIZE
  if (jc != NULL && jd != NULL)
    {
      /* we have to restransmit the ACK (if already available) */
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
                   "2xx restransmission receveid.\r\n"));
      /* check if the 2xx is for the same ACK */
      if (jd->d_ack != NULL && jd->d_ack->cseq != NULL
          && jd->d_ack->cseq->number != NULL)
        {
          if (0 ==
              osip_strcasecmp (jd->d_ack->cseq->number, evt->sip->cseq->number))
            {
              cb_snd_message (NULL, jd->d_ack, NULL, 0, -1);
              OSIP_TRACE (osip_trace
                          (__FILE__, __LINE__, OSIP_INFO1, NULL,
                           "ACK restransmission sent.\r\n"));
            }
        }

      osip_event_free (evt);
      return;
    }
#endif

  if (jc != NULL)
    {
      /* match answer with dialog */
      osip_dialog_t *dlg;
#ifndef MINISIZE
      osip_transaction_t *last_tr;
#endif
      int i;

      /* we match an existing dialog: send a retransmission of ACK */
      i = osip_dialog_init_as_uac (&dlg, evt->sip);
      if (i != 0 || dlg == NULL)
        {
          OSIP_TRACE (osip_trace
                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
                       "Cannot build dialog for 200ok.\r\n"));
          osip_event_free (evt);
          return;
        }

      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
                   "sending ACK for 2xx out of transaction.\r\n"));

      {
        osip_message_t *bye;
        char *transport = _eXosip_transport_protocol (evt->sip);
#ifndef MINISIZE                /* Don't send ACK in MINISIZE mode to save code 
size */
        osip_message_t *ack;
        if (transport == NULL)
          i = _eXosip_build_request_within_dialog (&ack, "ACK", dlg, "UDP");
        else
          i = _eXosip_build_request_within_dialog (&ack, "ACK", dlg, transport);
        if (i != 0)
          {
            osip_dialog_free (dlg);
            osip_event_free (evt);
            return;
          }
        /* copy all credentials from INVITE! */
        last_tr = jc->c_out_tr;
        if (last_tr != NULL)
          {
            int pos = 0;
            int i;
            osip_proxy_authorization_t *pa = NULL;

            i =
              osip_message_get_proxy_authorization (last_tr->orig_request, pos,
                                                    &pa);
            while (i >= 0 && pa != NULL)
              {
                osip_proxy_authorization_t *pa2;

                i = osip_proxy_authorization_clone (pa, &pa2);
                if (i != 0)
                  {
                    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, 
NULL,
                                            "Error in credential from 
INVITE\n"));
                    break;
                  }
                osip_list_add (&ack->proxy_authorizations, pa2, -1);
                pa = NULL;
                pos++;
                i =
                  osip_message_get_proxy_authorization (last_tr->orig_request, 
pos,
                                                        &pa);
              }
          }
        cb_snd_message (NULL, ack, NULL, 0, -1);
        osip_message_free (ack);
#endif
        /* in some case, PRACK and UPDATE may have been sent
           so we have to send a cseq which is above the previous
           one. */
        dlg->local_cseq = dlg->local_cseq + 4;

        /* ready to send a BYE */
        if (transport == NULL)
          i = generating_bye (&bye, dlg, "UDP");
        else
          i = generating_bye (&bye, dlg, transport);

//<<<<<<<<<<
        if(i != OSIP_SUCCESS) {
            if(bye) {
                osip_message_free (bye);
            }
        } else {
            cb_snd_message (NULL, bye, NULL, 0, -1);
            osip_message_free (bye);
        }
//>>>>>>>>>>
      }

      osip_dialog_free (dlg);
      osip_event_free (evt);
      return;
    }

  /* we don't match any existing dialog: send a ACK & send a BYE */
  osip_event_free (evt);
}

===============================================


Thanks,
Serg Ma




reply via email to

[Prev in Thread] Current Thread [Next in Thread]