Beispiel #1
0
int
_eXosip_pub_find_by_aor (struct eXosip_t *excontext, eXosip_pub_t ** pub, const char *aor)
{
  eXosip_pub_t *jpub;

  *pub = NULL;

  for (jpub = excontext->j_pub; jpub != NULL; jpub = jpub->next) {
    if (osip_strcasecmp (aor, jpub->p_aor) == 0) {
      *pub = jpub;
      return OSIP_SUCCESS;
    }
  }
  return OSIP_NOTFOUND;
}
Beispiel #2
0
void udp_tl_learn_port_from_via(osip_message_t * sip)
{
	/* EXOSIP_OPT_UDP_LEARN_PORT option set */
	if (eXosip.learn_port > 0) {
		osip_via_t *via = NULL;
		osip_generic_param_t *br;
		int i;

		i = osip_message_get_via(sip, 0, &via);
		if (i >= 0 && via != NULL && via->protocol != NULL
			&& (osip_strcasecmp(via->protocol, "udp") == 0
				|| osip_strcasecmp(via->protocol, "dtls-udp") == 0)) {
			osip_via_param_get_byname(via, "rport", &br);
			if (br != NULL && br->gvalue != NULL) {
				struct eXosip_account_info ainfo;
				memset(&ainfo, 0, sizeof(struct eXosip_account_info));
				snprintf(udp_firewall_port, sizeof(udp_firewall_port), "%s", br->gvalue);
				OSIP_TRACE(osip_trace
						   (__FILE__, __LINE__, OSIP_INFO1, NULL,
							"SIP port modified from rport in SIP answer\r\n"));

				osip_via_param_get_byname(via, "received", &br);
				if (br != NULL && br->gvalue != NULL
					&& sip->from != NULL && sip->from->url != NULL
					&& sip->from->url->host != NULL) {
					snprintf(ainfo.proxy, sizeof(ainfo.proxy), "%s",
							 sip->from->url->host);
					ainfo.nat_port = atoi(udp_firewall_port);
					snprintf(ainfo.nat_ip, sizeof(ainfo.nat_ip), "%s", br->gvalue);
					eXosip_set_option(EXOSIP_OPT_ADD_ACCOUNT_INFO, &ainfo);
				}
			}
		}
	}
	return;
}
Beispiel #3
0
sdp_media_t *
eXosip_get_media (sdp_message_t * sdp, const char *media)
{
  int pos = 0;
  sdp_media_t *med = (sdp_media_t *) osip_list_get (&sdp->m_medias, 0);

  while (med != NULL) {
    if (med->m_media != NULL && osip_strcasecmp (med->m_media, media) == 0)
      return med;
    pos++;
    med = (sdp_media_t *) osip_list_get (&sdp->m_medias, pos);
  }

  return NULL;
}
Beispiel #4
0
static int
_tcp_tl_find_socket (char *host, int port)
{
  int pos;

  for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++)
    {
      if (tcp_socket_tab[pos].socket != 0)
        {
          if (0 == osip_strcasecmp (tcp_socket_tab[pos].remote_ip, host)
              && port == tcp_socket_tab[pos].remote_port)
            return tcp_socket_tab[pos].socket;
        }
    }
  return -1;
}
int
eXosip_transport_set (osip_message_t * msg, const char *transport)
{
  osip_via_t *via;

  via = (osip_via_t *) osip_list_get (&msg->vias, 0);
  if (via == NULL || via->protocol == NULL)
    return -1;

  if (0 == osip_strcasecmp (via->protocol, transport))
    return 0;

  osip_free (via->protocol);
  via->protocol = osip_strdup (transport);
  return 0;
}
Beispiel #6
0
sdp_connection_t *eXosip_get_connection(sdp_message_t * sdp, const char *media)
{
	int pos = 0;
	sdp_media_t *med = (sdp_media_t *) osip_list_get(&sdp->m_medias, 0);

	while (med != NULL) {
		if (med->m_media != NULL && osip_strcasecmp(med->m_media, media) == 0)
			break;
		pos++;
		med = (sdp_media_t *) osip_list_get(&sdp->m_medias, pos);
	}
	if (med == NULL)
		return NULL;			/* no video stream */
	if (osip_list_eol(&med->c_connections, 0))
		return sdp->c_connection;

	/* just return the first one... */
	return (sdp_connection_t *) osip_list_get(&med->c_connections, 0);
}
Beispiel #7
0
/* and -1 on error. */
int
osip_message_header_get_byname(const osip_message_t * sip, const char *hname,
							   int pos, osip_header_t ** dest)
{
	int i;
	osip_header_t *tmp;

	*dest = NULL;
	i = pos;
	if (osip_list_size(&sip->headers) <= pos)
		return OSIP_UNDEFINED_ERROR;	/* NULL */
	while (osip_list_size(&sip->headers) > i) {
		tmp = (osip_header_t *) osip_list_get(&sip->headers, i);
		if (osip_strcasecmp(tmp->hname, hname) == 0) {
			*dest = tmp;
			return i;
		}
		i++;
	}
	return OSIP_UNDEFINED_ERROR;	/* not found */
}
Beispiel #8
0
int
eXosip_call_build_ack (int did, osip_message_t ** _ack)
{
  eXosip_dialog_t *jd = NULL;
  eXosip_call_t *jc = NULL;
  osip_transaction_t *tr = NULL;

  osip_message_t *ack;
  char *transport;
  int i;

  *_ack = NULL;

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

  tr = eXosip_find_last_invite (jc, jd);

  if (tr == NULL || tr->orig_request == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: No transaction for call?\n"));
      return OSIP_NOTFOUND;
    }

  if (0 != osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: ACK are only sent for invite transactions\n"));
      return OSIP_BADPARAMETER;
    }

  transport = NULL;
  transport = _eXosip_transport_protocol (tr->orig_request);
  if (transport == NULL)
    i = _eXosip_build_request_within_dialog (&ack, "ACK", jd->d_dialog, "UDP");
  else
    i = _eXosip_build_request_within_dialog (&ack, "ACK", jd->d_dialog, transport);

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

  _eXosip_call_reuse_contact (tr->orig_request, ack);

  /* Fix CSeq Number when request has been exchanged during INVITE transactions */
  if (tr->orig_request->cseq != NULL && tr->orig_request->cseq->number != NULL)
    {
      if (ack != NULL && ack->cseq != NULL && ack->cseq->number != NULL)
        {
          osip_free (ack->cseq->number);
          ack->cseq->number = osip_strdup (tr->orig_request->cseq->number);
        }
    }

  /* copy all credentials from INVITE! */
  {
    int pos = 0;
    osip_proxy_authorization_t *pa = NULL;

    i = osip_message_get_proxy_authorization (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 (tr->orig_request, pos, &pa);
      }
  }

  *_ack = ack;
  return OSIP_SUCCESS;
}
Beispiel #9
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;
}
Beispiel #10
0
/*
 * compares two URLs
 * (by now, only scheme, hostname and username are compared)
 *
 * RETURNS
 *	STS_SUCCESS if equal
 *	STS_FAILURE if non equal or error
 */
int compare_url(osip_uri_t *url1, osip_uri_t *url2) {
   int sts1, sts2;
   struct in_addr addr1, addr2;

   /* sanity checks */
   if ((url1 == NULL) || (url2 == NULL)) {
      ERROR("compare_url: NULL ptr: url1=0x%p, url2=0x%p",url1, url2);
      return STS_FAILURE;
   }

   /* sanity checks: host part is a MUST */
   if ((url1->host == NULL) || (url2->host == NULL)) {
      ERROR("compare_url: NULL ptr: url1->host=0x%p, url2->host=0x%p",
            url1->host, url2->host);
      return STS_FAILURE;
   }

   DEBUGC(DBCLASS_PROXY, "comparing urls: %s:%s@%s -> %s:%s@%s",
         (url1->scheme)   ? url1->scheme :   "(null)",
         (url1->username) ? url1->username : "******",
         (url1->host)     ? url1->host :     "(null)",
         (url2->scheme)   ? url2->scheme :   "(null)",
         (url2->username) ? url2->username : "******",
         (url2->host)     ? url2->host :     "(null)");

   /* compare SCHEME (if present) case INsensitive */
   if (url1->scheme && url2->scheme) {
      if (osip_strcasecmp(url1->scheme, url2->scheme) != 0) {
         DEBUGC(DBCLASS_PROXY, "compare_url: scheme mismatch");
         return STS_FAILURE;
      }
   } else {
      WARN("compare_url: NULL scheme - ignoring");
   }

   /* compare username (if present) case sensitive */
   if (url1->username && url2->username) {
      if (strcmp(url1->username, url2->username) != 0) {
         DEBUGC(DBCLASS_PROXY, "compare_url: username mismatch");
         return STS_FAILURE;
      }
   } else {
      DEBUGC(DBCLASS_PROXY, "compare_url: NULL username - ignoring");
   }


   /*
    * now, try to resolve the host. If resolveable, compare
    * IP addresses - if not resolveable, compare the host names
    * itselfes
    */

   /* get the IP addresses from the (possible) hostnames */
   sts1=get_ip_by_host(url1->host, &addr1);
   if (sts1 == STS_FAILURE) {
      DEBUGC(DBCLASS_PROXY, "compare_url: cannot resolve host [%s]",
             url1->host);
   }

   sts2=get_ip_by_host(url2->host, &addr2);
   if (sts2 == STS_FAILURE) {
      DEBUGC(DBCLASS_PROXY, "compare_url: cannot resolve host [%s]",
             url2->host);
   }

   if ((sts1 == STS_SUCCESS) && (sts2 == STS_SUCCESS)) {
      /* compare IP addresses */
      if (memcmp(&addr1, &addr2, sizeof(addr1))!=0) {
         DEBUGC(DBCLASS_PROXY, "compare_url: IP mismatch");
         return STS_FAILURE;
      }
   } else {
      /* compare hostname strings case INsensitive */
      if (osip_strcasecmp(url1->host, url2->host) != 0) {
         DEBUGC(DBCLASS_PROXY, "compare_url: host name mismatch");
         return STS_FAILURE;
      }
   }

   /* the two URLs did pass all tests successfully - MATCH */
   return STS_SUCCESS;
}
Beispiel #11
0
static int
eXtl_update_local_target (osip_message_t * req)
{
  int pos = 0;

  struct eXosip_account_info *ainfo = NULL;
  char *proxy = NULL;
  int i;
  if (MSG_IS_REQUEST (req))
    {
      if (req->from != NULL
          && req->from->url != NULL && req->from->url->host != NULL)
        proxy = req->from->url->host;
  } else
    {
      if (req->to != NULL && req->to->url != NULL && req->to->url->host != NULL)
        proxy = req->to->url->host;
    }

  if (proxy != NULL)
    {
      for (i = 0; i < MAX_EXOSIP_ACCOUNT_INFO; i++)
        {
          if (eXosip.account_entries[i].proxy[0] != '\0')
            {
              if (strstr (eXosip.account_entries[i].proxy, proxy) != NULL
                  || strstr (proxy, eXosip.account_entries[i].proxy) != NULL)
                {
                  /* use ainfo */
                  if (eXosip.account_entries[i].nat_ip[0] != '\0')
                    {
                      ainfo = &eXosip.account_entries[i];
                      break;
                    }
                }
            }
        }
    }

  if (udp_firewall_ip != '\0')
    {

      while (!osip_list_eol (&req->contacts, pos))
        {
          osip_contact_t *co;

          co = (osip_contact_t *) osip_list_get (&req->contacts, pos);
          pos++;
          if (co != NULL && co->url != NULL && co->url->host != NULL
              && 0 == osip_strcasecmp (co->url->host, udp_firewall_ip))
            {
              if (ainfo == NULL)
                {
                  if (co->url->port == NULL &&
                      0 != osip_strcasecmp (udp_firewall_port, "5060"))
                    {
                      co->url->port = osip_strdup (udp_firewall_port);
                  } else if (co->url->port != NULL &&
                             0 != osip_strcasecmp (udp_firewall_port,
                                                   co->url->port))
                    {
                      osip_free (co->url->port);
                      co->url->port = osip_strdup (udp_firewall_port);
                    }
              } else
                {
                  if (co->url->port == NULL && ainfo->nat_port != 5060)
                    {
                      co->url->port = osip_malloc (10);
                      if (co->url->port == NULL)
                        return OSIP_NOMEM;
                      snprintf (co->url->port, 9, "%i", ainfo->nat_port);
                  } else if (co->url->port != NULL &&
                             ainfo->nat_port != atoi (co->url->port))
                    {
                      osip_free (co->url->port);
                      co->url->port = osip_malloc (10);
                      if (co->url->port == NULL)
                        return OSIP_NOMEM;
                      snprintf (co->url->port, 9, "%i", ainfo->nat_port);
                    }
                }
            }
        }
    }

  return OSIP_SUCCESS;
}
Beispiel #12
0
int
eXosip_add_authentication_information (osip_message_t * req,
                                       osip_message_t * last_response)
{
  osip_authorization_t *aut = NULL;
  osip_www_authenticate_t *wwwauth = NULL;
  osip_proxy_authorization_t *proxy_aut = NULL;
  osip_proxy_authenticate_t *proxyauth = NULL;
  jauthinfo_t *authinfo = NULL;
  int pos;
  int i;

  if (req == NULL
      || req->from == NULL
      || req->from->url == NULL || req->from->url->username == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
                   "authinfo: Invalid message\n"));
      return -1;
   }

  if (last_response==NULL)
  {
	  /* we can add all credential that belongs to the same call-id */
	struct eXosip_http_auth *http_auth;
	int pos;

	/* update entries with same call_id */
	for (pos=0;pos<MAX_EXOSIP_HTTP_AUTH;pos++)
	{
		http_auth = &eXosip.http_auths[pos];
		if (http_auth->pszCallId[0]=='\0')
			continue;
		if (osip_strcasecmp(http_auth->pszCallId, req->call_id->number)==0)
		{
			char *uri;

			authinfo = eXosip_find_authentication_info (req->from->url->username,
												  http_auth->wa->realm);
			if (authinfo == NULL)
			{
				OSIP_TRACE (osip_trace
						  (__FILE__, __LINE__, OSIP_INFO2, NULL,
						   "authinfo: No authentication found for %s %s\n",
						   req->from->url->username, http_auth->wa->realm));
				return -1;
			}

			i = osip_uri_to_str (req->req_uri, &uri);
			if (i != 0)
				return -1;

			http_auth->iNonceCount++;
			if (osip_strcasecmp(req->sip_method, "REGISTER")==0)
				i = __eXosip_create_authorization_header (http_auth->wa, uri,
													authinfo->userid,
													authinfo->passwd,
													authinfo->ha1, &aut,
													req->sip_method,
													http_auth->pszCNonce,
													http_auth->iNonceCount);
			else
				i = __eXosip_create_proxy_authorization_header (http_auth->wa, uri,
													authinfo->userid,
													authinfo->passwd,
													authinfo->ha1, &aut,
													req->sip_method,
													http_auth->pszCNonce,
													http_auth->iNonceCount);

			osip_free (uri);
			if (i != 0)
				return -1;

			if (aut != NULL)
			{
				if (osip_strcasecmp(req->sip_method, "REGISTER")==0)
					osip_list_add (&req->authorizations, aut, -1);
				else
					osip_list_add (&req->proxy_authorizations, aut, -1);
				osip_message_force_update (req);
			}
		}
	}
	return 0;
  }

  pos = 0;
  osip_message_get_www_authenticate (last_response, pos, &wwwauth);
  osip_message_get_proxy_authenticate (last_response, pos, &proxyauth);
  if (wwwauth == NULL && proxyauth == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
                   "authinfo: No WWW-Authenticate or Proxy-Authenticate\n"));
      return -1;
    }

  while (wwwauth != NULL)
    {
      char *uri;

      authinfo = eXosip_find_authentication_info (req->from->url->username,
                                                  wwwauth->realm);
      if (authinfo == NULL)
        {
          OSIP_TRACE (osip_trace
                      (__FILE__, __LINE__, OSIP_INFO2, NULL,
                       "authinfo: No authentication found for %s %s\n",
                       req->from->url->username, wwwauth->realm));
          return -1;
        }

      i = osip_uri_to_str (req->req_uri, &uri);
      if (i != 0)
        return -1;

      i = __eXosip_create_authorization_header (wwwauth, uri,
                                                authinfo->userid,
                                                authinfo->passwd,
                                                authinfo->ha1, &aut,
                                                req->sip_method,
												"0a4f113b",
												1);
      osip_free (uri);
      if (i != 0)
        return -1;

      if (aut != NULL)
        {
          osip_list_add (&req->authorizations, aut, -1);
          osip_message_force_update (req);
        }

	  if (wwwauth->qop_options!=NULL)
	  {
		  if (osip_strcasecmp(req->sip_method, "REGISTER")==0
			  || osip_strcasecmp(req->sip_method, "INVITE")==0
  			  || osip_strcasecmp(req->sip_method, "SUBSCRIBE")==0)
		  	  _eXosip_store_nonce(req->call_id->number, wwwauth);
		  else
		  {
			  osip_generic_param_t *to_tag=NULL;
			  osip_from_param_get_byname (req->to, "tag", &to_tag);
			  if (to_tag!=NULL)
			  {
				  /* if message is part of a dialog */
			  	  _eXosip_store_nonce(req->call_id->number, wwwauth);
			  }
		  }
	  }

      pos++;
      osip_message_get_www_authenticate (last_response, pos, &wwwauth);
    }

  pos = 0;
  while (proxyauth != NULL)
    {
      char *uri;

      authinfo = eXosip_find_authentication_info (req->from->url->username,
                                                  proxyauth->realm);
      if (authinfo == NULL)
        {
          OSIP_TRACE (osip_trace
                      (__FILE__, __LINE__, OSIP_INFO2, NULL,
                       "authinfo: No authentication found for %s %s\n",
                       req->from->url->username, proxyauth->realm));
          return -1;
        }
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
                   "authinfo: %s\n", authinfo->username));
      i = osip_uri_to_str (req->req_uri, &uri);
      if (i != 0)
        return -1;

      i = __eXosip_create_proxy_authorization_header (proxyauth, uri,
                                                      authinfo->userid,
                                                      authinfo->passwd,
                                                      authinfo->ha1,
                                                      &proxy_aut, req->sip_method,
													  "0a4f113b",
													  1);
      osip_free (uri);
      if (i != 0)
        return -1;

      if (proxy_aut != NULL)
        {
          osip_list_add (&req->proxy_authorizations, proxy_aut, -1);
          osip_message_force_update (req);
        }

	  if (proxyauth->qop_options!=NULL)
	  {
		  if (osip_strcasecmp(req->sip_method, "REGISTER")==0
			  || osip_strcasecmp(req->sip_method, "INVITE")==0
  			  || osip_strcasecmp(req->sip_method, "SUBSCRIBE")==0)
		  	  _eXosip_store_nonce(req->call_id->number, proxyauth);
		  else
		  {
			  osip_generic_param_t *to_tag=NULL;
			  osip_from_param_get_byname (req->to, "tag", &to_tag);
			  if (to_tag!=NULL)
			  {
				  /* if message is part of a dialog */
			  	  _eXosip_store_nonce(req->call_id->number, proxyauth);
			  }
		  }
	  }

      pos++;
      osip_message_get_proxy_authenticate (last_response, pos, &proxyauth);
    }

  return 0;
}
Beispiel #13
0
int
generating_register (eXosip_reg_t * jreg, osip_message_t ** reg, char *transport,
                     char *from, char *proxy, char *contact, int expires)
{
  int i;
  char locip[65];
  char firewall_ip[65];
  char firewall_port[10];
  if (eXosip.eXtl == NULL)
    return OSIP_NO_NETWORK;

  if (eXosip.eXtl->tl_get_masquerade_contact != NULL)
    {
      eXosip.eXtl->tl_get_masquerade_contact (firewall_ip, sizeof (firewall_ip),
                                              firewall_port,
                                              sizeof (firewall_port));
    }

  i =
    generating_request_out_of_dialog (reg, "REGISTER", NULL, transport, from,
                                      proxy);
  if (i != 0)
    return i;

  memset (locip, '\0', sizeof (locip));
  eXosip_guess_ip_for_via (eXosip.eXtl->proto_family, locip, 49);

  if (locip[0] == '\0')
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: no default interface defined\n"));
      osip_message_free (*reg);
      *reg = NULL;
      return OSIP_NO_NETWORK;
    }

  if (contact == NULL)
    {
      osip_contact_t *new_contact = NULL;
      osip_uri_t *new_contact_url = NULL;

      i = osip_contact_init (&new_contact);
      if (i == 0)
        i = osip_uri_init (&new_contact_url);

      new_contact->url = new_contact_url;

      if (i == 0 && (*reg)->from != NULL
          && (*reg)->from->url != NULL && (*reg)->from->url->username != NULL)
        {
          new_contact_url->username = osip_strdup ((*reg)->from->url->username);
        }

      if (i == 0 && (*reg)->from != NULL && (*reg)->from->url != NULL)
        {
          /* serach for correct ip */
          if (firewall_ip[0] != '\0')
            {
              char *c_address = (*reg)->req_uri->host;

              struct addrinfo *addrinfo;
              struct __eXosip_sockaddr addr;

              i =
                eXosip_get_addrinfo (&addrinfo, (*reg)->req_uri->host, 5060,
                                     IPPROTO_UDP);
              if (i == 0)
                {
                  memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
                  eXosip_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))
                {
                  new_contact_url->host = osip_strdup (firewall_ip);
                  new_contact_url->port = osip_strdup (firewall_port);
              } else
                {
                  new_contact_url->host = osip_strdup (locip);
                  new_contact_url->port = osip_strdup (firewall_port);
                }
          } else
            {
              new_contact_url->host = osip_strdup (locip);
              new_contact_url->port = osip_strdup (firewall_port);
            }

          if (transport != NULL && osip_strcasecmp (transport, "UDP") != 0)
            {
              osip_uri_uparam_add (new_contact_url, osip_strdup ("transport"),
                                   osip_strdup (transport));
            }

          if (jreg->r_line[0] != '\0')
            {
              osip_uri_uparam_add (new_contact_url, osip_strdup ("line"),
                                   osip_strdup (jreg->r_line));
            }

          osip_list_add (&(*reg)->contacts, new_contact, -1);
        }
  } else
    {
      osip_message_set_contact (*reg, contact);
    }

  {
    char exp[10];               /* MUST never be ouside 1 and 3600 */

    snprintf (exp, 9, "%i", expires);
    osip_message_set_expires (*reg, exp);
  }

  osip_message_set_content_length (*reg, "0");

  return OSIP_SUCCESS;
}
Beispiel #14
0
int
eXosip_call_send_answer (int tid, int status, osip_message_t * answer)
{
  eXosip_dialog_t *jd = NULL;
  eXosip_call_t *jc = NULL;
  osip_transaction_t *tr = NULL;
  osip_event_t *evt_answer;

  if (tid < 0)
    {
      osip_message_free (answer);
      return OSIP_BADPARAMETER;
    }
  if (status <= 100)
    {
      osip_message_free (answer);
      return OSIP_BADPARAMETER;
    }
  if (status > 699)
    {
      osip_message_free (answer);
      return OSIP_BADPARAMETER;
    }

  if (tid > 0)
    {
      _eXosip_call_transaction_find (tid, &jc, &jd, &tr);
    }
  if (jd == NULL || tr == NULL || tr->orig_request == NULL
      || tr->orig_request->sip_method == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: No call here or no transaction for call\n"));
      osip_message_free (answer);
      return OSIP_NOTFOUND;
    }

  if (answer == NULL)
    {
      if (0 == osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
        {
          if (status >= 200 && status <= 299)
            {
              OSIP_TRACE (osip_trace
                          (__FILE__, __LINE__, OSIP_ERROR, NULL,
                           "eXosip: Wrong parameter?\n"));
              osip_message_free (answer);
              return OSIP_BADPARAMETER;
            }
        }
    }

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

  if (answer == NULL)
    {
      if (0 == osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
        {
          osip_message_t *response;
          return _eXosip_answer_invite_123456xx (jc, jd, status, &response, 1);
        }
      osip_message_free (answer);
      return OSIP_BADPARAMETER;
    }

  if (0 == osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
    {
      if (MSG_IS_STATUS_2XX (answer) && jd != NULL)
        {
          if (status >= 200 && status < 300 && jd != NULL)
            {
              eXosip_dialog_set_200ok (jd, answer);
              /* wait for a ACK */
              osip_dialog_set_state (jd->d_dialog, DIALOG_CONFIRMED);
            }
        }
    }

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

  osip_transaction_add_event (tr, evt_answer);
  eXosip_update ();
  __eXosip_wakeup ();
  return OSIP_SUCCESS;
}
static int
msg_osip_body_parse(osip_message_t * sip, const char *start_of_buf,
					const char **next_body, size_t length)
{
	const char *start_of_body;
	const char *end_of_body;
	const char *end_of_buf;
	char *tmp;
	int i;

	char *sep_boundary;
	size_t len_sep_boundary;
	osip_generic_param_t *ct_param;

	if (sip->content_type == NULL
		|| sip->content_type->type == NULL || sip->content_type->subtype == NULL)
		return OSIP_SUCCESS;	/* no body is attached */

	if (0 != osip_strcasecmp(sip->content_type->type, "multipart")) {
		size_t osip_body_len;

		if (start_of_buf[0] == '\0')
			return OSIP_SYNTAXERROR;	/* final CRLF is missing */
		/* get rid of the first CRLF */
		if ('\r' == start_of_buf[0]) {
			if ('\n' == start_of_buf[1])
				start_of_body = start_of_buf + 2;
			else
				start_of_body = start_of_buf + 1;
		} else if ('\n' == start_of_buf[0])
			start_of_body = start_of_buf + 1;
		else
			return OSIP_SYNTAXERROR;	/* message does not end with CRLFCRLF, CRCR or LFLF */

		/* update length (without CRLFCRLF */
		length = length - (start_of_body - start_of_buf);	/* fixed 24 08 2004 */
		if (length <= 0)
			return OSIP_SYNTAXERROR;

		if (sip->content_length != NULL)
			osip_body_len = osip_atoi(sip->content_length->value);
		else {
			/* if content_length does not exist, set it. */
			char tmp[16];

			/* case where content-length is missing but the
			   body only contains non-binary data */
			if (0 == osip_strcasecmp(sip->content_type->type, "application")
				&& 0 == osip_strcasecmp(sip->content_type->subtype, "sdp")) {
				osip_body_len = strlen(start_of_body);
				sprintf(tmp, "%i", osip_body_len);
				i = osip_message_set_content_length(sip, tmp);
				if (i != 0)
					return i;
			} else
				return OSIP_SYNTAXERROR;	/* Content-type may be non binary data */
		}

		if (length < osip_body_len) {
			OSIP_TRACE(osip_trace
					   (__FILE__, __LINE__, OSIP_ERROR, NULL,
						"Message was not receieved enterely. length=%i osip_body_len=%i\n",
						length, osip_body_len));
			return OSIP_SYNTAXERROR;
		}

		end_of_body = start_of_body + osip_body_len;
		tmp = osip_malloc(end_of_body - start_of_body + 2);
		if (tmp == NULL)
			return OSIP_NOMEM;
		memcpy(tmp, start_of_body, end_of_body - start_of_body);
		tmp[end_of_body - start_of_body] = '\0';

		i = osip_message_set_body(sip, tmp, end_of_body - start_of_body);
		osip_free(tmp);
		if (i != 0)
			return i;
		return OSIP_SUCCESS;
	}

	/* find the boundary */
	i = osip_generic_param_get_byname(&sip->content_type->gen_params,
									  "boundary", &ct_param);
	if (i != 0)
		return i;

	if (ct_param == NULL)
		return OSIP_SYNTAXERROR;
	if (ct_param->gvalue == NULL)
		return OSIP_SYNTAXERROR;	/* No boundary but multiple headers??? */

	{
		const char *boundary_prefix = "\n--";

		size_t len = strlen(ct_param->gvalue);

		sep_boundary = (char *) osip_malloc(len + 4);
		if (sep_boundary == NULL)
			return OSIP_NOMEM;
		strcpy(sep_boundary, boundary_prefix);
		if (ct_param->gvalue[0] == '"' && ct_param->gvalue[len - 1] == '"')
			strncat(sep_boundary, ct_param->gvalue + 1, len - 2);
		else
			strncat(sep_boundary, ct_param->gvalue, len);
	}

	len_sep_boundary = strlen(sep_boundary);

	*next_body = NULL;
	start_of_body = start_of_buf;

	end_of_buf = start_of_buf + length;

	for (;;) {
		size_t body_len = 0;

		i = __osip_find_next_occurence(sep_boundary, start_of_body,
									   &start_of_body, end_of_buf);
		if (i != 0) {
			osip_free(sep_boundary);
			return i;
		}

		i = __osip_find_next_occurence(sep_boundary,
									   start_of_body + len_sep_boundary,
									   &end_of_body, end_of_buf);
		if (i != 0) {
			osip_free(sep_boundary);
			return i;
		}

		/* this is the real beginning of body */
		start_of_body = start_of_body + len_sep_boundary + 1;
		if ('\n' == start_of_body[0] || '\r' == start_of_body[0])
			start_of_body++;

		body_len = end_of_body - start_of_body;

		/* Skip CR before end boundary. */
		if (*(end_of_body - 1) == '\r')
			body_len--;

		tmp = osip_malloc(body_len + 2);
		if (tmp == NULL) {
			osip_free(sep_boundary);
			return OSIP_NOMEM;
		}
		memcpy(tmp, start_of_body, body_len);
		tmp[body_len] = '\0';

		i = osip_message_set_body_mime(sip, tmp, body_len);
		osip_free(tmp);
		if (i != 0) {
			osip_free(sep_boundary);
			return i;
		}

		if (strncmp(end_of_body + len_sep_boundary, "--", 2) == 0) {	/* end of all bodies */
			*next_body = end_of_body;
			osip_free(sep_boundary);
			return OSIP_SUCCESS;
		}

		/* continue on the next body */
		start_of_body = end_of_body;
	}
	/* Unreachable code */
	/* osip_free (sep_boundary); */
	return OSIP_SYNTAXERROR;
}
static int
__osip_message_startline_parsereq(osip_message_t * dest, const char *buf,
								  const char **headers)
{
	const char *p1;
	const char *p2;
	char *requesturi;
	int i;

	dest->sip_method = NULL;
	dest->status_code = 0;
	dest->reason_phrase = NULL;

	*headers = buf;

	/* The first token is the method name: */
	p2 = strchr(buf, ' ');
	if (p2 == NULL)
		return OSIP_SYNTAXERROR;
	if (*(p2 + 1) == '\0' || *(p2 + 2) == '\0')
		return OSIP_SYNTAXERROR;
	if (p2 - buf == 0) {
		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_ERROR, NULL,
					"No space allowed here\n"));
		return OSIP_SYNTAXERROR;
	}
	dest->sip_method = (char *) osip_malloc(p2 - buf + 1);
	if (dest->sip_method == NULL)
		return OSIP_NOMEM;
	osip_strncpy(dest->sip_method, buf, p2 - buf);

	/* The second token is a sip-url or a uri: */
	p1 = strchr(p2 + 2, ' ');	/* no space allowed inside sip-url */
	if (p1 == NULL) {
		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_ERROR, NULL,
					"Uncompliant request-uri\n"));
		osip_free(dest->sip_method);
		dest->sip_method = NULL;
		return OSIP_SYNTAXERROR;
	}
	if (p1 - p2 < 2) {
		osip_free(dest->sip_method);
		dest->sip_method = NULL;
		return OSIP_SYNTAXERROR;
	}

	requesturi = (char *) osip_malloc(p1 - p2);
	if (requesturi == NULL) {
		osip_free(dest->sip_method);
		dest->sip_method = NULL;
		return OSIP_NOMEM;
	}
	osip_clrncpy(requesturi, p2 + 1, (p1 - p2 - 1));

	i = osip_uri_init(&(dest->req_uri));
	if (i != 0) {
		osip_free(requesturi);
		requesturi = NULL;
		osip_free(dest->sip_method);
		dest->sip_method = NULL;
		return OSIP_NOMEM;
	}
	i = osip_uri_parse(dest->req_uri, requesturi);
	osip_free(requesturi);
	if (i != 0) {
		osip_free(dest->sip_method);
		dest->sip_method = NULL;
		osip_uri_free(dest->req_uri);
		dest->req_uri = NULL;
		return OSIP_SYNTAXERROR;
	}

	/* find the the version and the beginning of headers */
	{
		const char *hp = p1;

		while ((*hp != '\r') && (*hp != '\n')) {
			if (*hp)
				hp++;
			else {
				OSIP_TRACE(osip_trace
						   (__FILE__, __LINE__, OSIP_ERROR, NULL,
							"No crlf found\n"));
				osip_free(dest->sip_method);
				dest->sip_method = NULL;
				osip_uri_free(dest->req_uri);
				dest->req_uri = NULL;
				return OSIP_SYNTAXERROR;
			}
		}
		if (hp - p1 < 2) {
			osip_free(dest->sip_method);
			dest->sip_method = NULL;
			osip_uri_free(dest->req_uri);
			dest->req_uri = NULL;
			return OSIP_SYNTAXERROR;
		}

		dest->sip_version = (char *) osip_malloc(hp - p1);
		if (dest->sip_version == NULL) {
			osip_free(dest->sip_method);
			dest->sip_method = NULL;
			osip_uri_free(dest->req_uri);
			dest->req_uri = NULL;
			return OSIP_NOMEM;
		}

		osip_strncpy(dest->sip_version, p1 + 1, (hp - p1 - 1));

		if (0 != osip_strcasecmp(dest->sip_version, "SIP/2.0")) {
			OSIP_TRACE(osip_trace
					   (__FILE__, __LINE__, OSIP_ERROR, NULL,
						"Wrong version number\n"));
		}

		hp++;
		if ((*hp) && ('\r' == hp[-1]) && ('\n' == hp[0]))
			hp++;
		(*headers) = hp;
	}
	return OSIP_SUCCESS;
}
Beispiel #17
0
int
__osip_ict_init (osip_ict_t ** ict, osip_t * osip, osip_message_t * invite)
{
  osip_route_t *route;
  int i;

  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "allocating ICT context\n"));

  *ict = (osip_ict_t *) osip_malloc (sizeof (osip_ict_t));
  if (*ict == NULL)
    return OSIP_NOMEM;

  memset (*ict, 0, sizeof (osip_ict_t));
  /* for INVITE retransmissions */
  {
    osip_via_t *via;
    char *proto;

    i = osip_message_get_via (invite, 0, &via); /* get top via */
    if (i < 0) {
      osip_free (*ict);
      return i;
    }
    proto = via_get_protocol (via);
    if (proto == NULL) {
      osip_free (*ict);
      return OSIP_SYNTAXERROR;
    }
#ifdef USE_BLOCKINGSOCKET
    if (osip_strcasecmp (proto, "TCP") != 0 && osip_strcasecmp (proto, "TLS") != 0 && osip_strcasecmp (proto, "SCTP") != 0) {   /* for other reliable protocol than TCP, the timer
                                                                                                                                   must be desactived by the external application */
      (*ict)->timer_a_length = DEFAULT_T1;
      if (64 * DEFAULT_T1 < 32000)
        (*ict)->timer_d_length = 32000;
      else
        (*ict)->timer_d_length = 64 * DEFAULT_T1;
      osip_gettimeofday (&(*ict)->timer_a_start, NULL);
      add_gettimeofday (&(*ict)->timer_a_start, (*ict)->timer_a_length);
      (*ict)->timer_d_start.tv_sec = -1;        /* not started */
    }
    else {                      /* reliable protocol is used: */
      (*ict)->timer_a_length = -1;      /* A is not ACTIVE */
      (*ict)->timer_d_length = 0;       /* MUST do the transition immediatly */
      (*ict)->timer_a_start.tv_sec = -1;        /* not started */
      (*ict)->timer_d_start.tv_sec = -1;        /* not started */
    }
  }
#else
    if (osip_strcasecmp (proto, "TCP") != 0 && osip_strcasecmp (proto, "TLS") != 0 && osip_strcasecmp (proto, "SCTP") != 0) {   /* for other reliable protocol than TCP, the timer
                                                                                                                                   must be desactived by the external application */
      (*ict)->timer_a_length = DEFAULT_T1;
      if (64 * DEFAULT_T1 < 32000)
        (*ict)->timer_d_length = 32000;
      else
        (*ict)->timer_d_length = 64 * DEFAULT_T1;
      osip_gettimeofday (&(*ict)->timer_a_start, NULL);
      add_gettimeofday (&(*ict)->timer_a_start, (*ict)->timer_a_length);
      (*ict)->timer_d_start.tv_sec = -1;        /* not started */
    }
    else {                      /* reliable protocol is used: */
      (*ict)->timer_a_length = DEFAULT_T1;
      (*ict)->timer_d_length = 0;       /* MUST do the transition immediatly */
      osip_gettimeofday (&(*ict)->timer_a_start, NULL);
      add_gettimeofday (&(*ict)->timer_a_start, (*ict)->timer_a_length);
      (*ict)->timer_d_start.tv_sec = -1;        /* not started */
    }
  }
Beispiel #18
0
static int
udp_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host,
					int port, int out_socket)
{
	int len = 0;
	size_t length = 0;
	struct addrinfo *addrinfo;
	struct __eXosip_sockaddr addr;
	char *message = NULL;

	char ipbuf[INET6_ADDRSTRLEN];
	int i;
	osip_naptr_t *naptr_record=NULL;

	if (udp_socket <= 0)
		return -1;

	if (host == NULL) {
		host = sip->req_uri->host;
		if (sip->req_uri->port != NULL)
			port = osip_atoi(sip->req_uri->port);
		else
			port = 5060;
	}

	eXtl_update_local_target(sip);

	i = -1;
#ifndef MINISIZE
	if (tr==NULL)
	{
		_eXosip_srv_lookup(sip, &naptr_record);

		if (naptr_record!=NULL) {
			eXosip_dnsutils_dns_process(naptr_record, 1);
			if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NAPTRDONE
				||naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVINPROGRESS)
				eXosip_dnsutils_dns_process(naptr_record, 1);
		}

		if (naptr_record!=NULL && naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVDONE)
		{
			/* 4: check if we have the one we want... */
			if (naptr_record->sipudp_record.name[0] != '\0'
				&& naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0] != '\0') {
					/* always choose the first here.
					if a network error occur, remove first entry and
					replace with next entries.
					*/
					osip_srv_entry_t *srv;
					int n = 0;
					for (srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index];
						n < 10 && naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0];
						srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index]) {
							if (srv->ipaddress[0])
								i = eXosip_get_addrinfo(&addrinfo, srv->ipaddress, srv->port, IPPROTO_UDP);
							else
								i = eXosip_get_addrinfo(&addrinfo, srv->srv, srv->port, IPPROTO_UDP);
							if (i == 0) {
								host = srv->srv;
								port = srv->port;
								break;
							}

							i = eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record);
							if (i<=0)
							{
								return -1;
							}
							if (i>=n)
							{
								return -1;
							}
							i = -1;
							/* copy next element */
							n++;
					}
			}
		}

		if (naptr_record!=NULL && naptr_record->keep_in_cache==0)
			osip_free(naptr_record);
		naptr_record=NULL;
	}
	else
	{
		naptr_record = tr->naptr_record;
	}

	if (naptr_record!=NULL)
	{
		/* 1: make sure there is no pending DNS */
		eXosip_dnsutils_dns_process(naptr_record, 0);
		if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NAPTRDONE
			||naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVINPROGRESS)
			eXosip_dnsutils_dns_process(naptr_record, 0);

		if (naptr_record->naptr_state==OSIP_NAPTR_STATE_UNKNOWN)
		{
			/* fallback to DNS A */
			if (naptr_record->keep_in_cache==0)
				osip_free(naptr_record);
			naptr_record=NULL;
			if (tr!=NULL)
				tr->naptr_record=NULL;
			/* must never happen? */
		}
		else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_INPROGRESS)
		{
			/* 2: keep waiting (naptr answer not received) */
			return OSIP_SUCCESS + 1;
		}
		else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NAPTRDONE)
		{
			/* 3: keep waiting (naptr answer received/no srv answer received) */
			return OSIP_SUCCESS + 1;
		}
		else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVINPROGRESS)
		{
			/* 3: keep waiting (naptr answer received/no srv answer received) */
			return OSIP_SUCCESS + 1;
		}
		else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVDONE)
		{
			/* 4: check if we have the one we want... */
			if (naptr_record->sipudp_record.name[0] != '\0'
				&& naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0] != '\0') {
					/* always choose the first here.
					if a network error occur, remove first entry and
					replace with next entries.
					*/
					osip_srv_entry_t *srv;
					int n = 0;
					for (srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index];
						n < 10 && naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0];
						srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index]) {
							if (srv->ipaddress[0])
								i = eXosip_get_addrinfo(&addrinfo, srv->ipaddress, srv->port, IPPROTO_UDP);
							else
								i = eXosip_get_addrinfo(&addrinfo, srv->srv, srv->port, IPPROTO_UDP);
							if (i == 0) {
								host = srv->srv;
								port = srv->port;
								break;
							}

							i = eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record);
							if (i<=0)
							{
								return -1;
							}
							if (i>=n)
							{
								return -1;
							}
							i = -1;
							/* copy next element */
							n++;
					}
			}
		}
		else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NOTSUPPORTED
			||naptr_record->naptr_state==OSIP_NAPTR_STATE_RETRYLATER)
		{
			/* 5: fallback to DNS A */
			if (naptr_record->keep_in_cache==0)
				osip_free(naptr_record);
			naptr_record=NULL;
			if (tr!=NULL)
				tr->naptr_record=NULL;
		}
	}
#endif

	/* if SRV was used, destination may be already found */
	if (i != 0) {
		i = eXosip_get_addrinfo(&addrinfo, host, port, IPPROTO_UDP);
	}

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

	memcpy(&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
	len = addrinfo->ai_addrlen;

	eXosip_freeaddrinfo(addrinfo);

	/* remove preloaded route if there is no tag in the To header
	 */
	{
		osip_route_t *route = NULL;
		osip_generic_param_t *tag = NULL;
		osip_message_get_route(sip, 0, &route);

		osip_to_get_tag(sip->to, &tag);
		if (tag == NULL && route != NULL && route->url != NULL) {
			osip_list_remove(&sip->routes, 0);
		}
		i = osip_message_to_str(sip, &message, &length);
		if (tag == NULL && route != NULL && route->url != NULL) {
			osip_list_add(&sip->routes, route, 0);
		}
	}

	if (i != 0 || length <= 0) {
		osip_free(message);
		return -1;
	}

	switch (((struct sockaddr *) &addr)->sa_family) {
	case AF_INET:
		inet_ntop(((struct sockaddr *) &addr)->sa_family,
				  &(((struct sockaddr_in *) &addr)->sin_addr), ipbuf,
				  sizeof(ipbuf));
		break;
	case AF_INET6:
		inet_ntop(((struct sockaddr *) &addr)->sa_family,
				  &(((struct sockaddr_in6 *) &addr)->sin6_addr), ipbuf,
				  sizeof(ipbuf));
		break;
	default:
		strncpy(ipbuf, "(unknown)", sizeof(ipbuf));
		break;
	}

	OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
						  "Message sent: (to dest=%s:%i)\n%s\n",
						  ipbuf, port, message));

	if (osip_strcasecmp(host, ipbuf)!=0 && MSG_IS_REQUEST(sip)) {
		if (MSG_IS_REGISTER(sip)) {
			struct eXosip_dns_cache entry;

			memset(&entry, 0, sizeof(struct eXosip_dns_cache));
			snprintf(entry.host, sizeof(entry.host), "%s", host);
			snprintf(entry.ip, sizeof(entry.ip), "%s", ipbuf);
			eXosip_set_option(EXOSIP_OPT_ADD_DNS_CACHE, (void *) &entry);
		}
	}

	if (tr != NULL) {
		if (tr->ict_context != NULL)
			osip_ict_set_destination(tr->ict_context, osip_strdup(ipbuf), port);
		if (tr->nict_context != NULL)
			osip_nict_set_destination(tr->nict_context, osip_strdup(ipbuf), port);
	}

	if (0 >
		sendto(udp_socket, (const void *) message, length, 0,
			   (struct sockaddr *) &addr, len))
	{
#ifndef MINISIZE
		if (naptr_record!=NULL)
		{
			/* rotate on failure! */
			if (eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record)>0)
			{
				osip_free(message);
				return OSIP_SUCCESS + 1;	/* retry for next retransmission! */
			}
		}
#endif
		/* SIP_NETWORK_ERROR; */
		osip_free(message);
		return -1;
	}
	
	if (eXosip.keep_alive > 0) {
		if (MSG_IS_REGISTER(sip)) {
			eXosip_reg_t *reg = NULL;

			if (_eXosip_reg_find(&reg, tr) == 0) {
				memcpy(&(reg->addr), &addr, len);
				reg->len = len;
			}
		}
	}

#ifndef MINISIZE
	if (naptr_record!=NULL)
	{
		if (tr!=NULL && MSG_IS_REGISTER(sip) && tr->last_response==NULL)
		{
			/* failover for outgoing transaction */
			time_t now;
			now = time(NULL);
			OSIP_TRACE(osip_trace
				(__FILE__, __LINE__, OSIP_INFO2, NULL,
				"not yet answered\n"));
			if (tr != NULL && now - tr->birth_time > 10 && now - tr->birth_time < 13)
			{
				/* avoid doing this twice... */
				if (eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record)>0)
				{
					OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
						"Doing failover: %s:%i->%s:%i\n",
						host, port,
						naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv,
						naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].port));
					osip_free(message);
					return OSIP_SUCCESS + 1;	/* retry for next retransmission! */
				}
			}
		}
	}
#endif

	osip_free(message);
	return OSIP_SUCCESS;
}
Beispiel #19
0
int
_eXosip_complete_answer_that_establish_a_dialog (struct eXosip_t *excontext, osip_message_t * response, osip_message_t * request)
{
  int i;
  int route_found = 0;
  char contact[1024];
  char scheme[10];
  osip_list_iterator_t it;
  osip_record_route_t *rr;

  snprintf(scheme, sizeof(scheme), "sip");

  /* 12.1.1:
     copy all record-route in response
     add a contact with global scope
   */
  rr = (osip_record_route_t *)osip_list_get_first(&request->record_routes, &it);
  while (rr != NULL) {
    osip_record_route_t *rr2;

    i = osip_record_route_clone (rr, &rr2);
    if (i != 0)
      return i;
    osip_list_add (&response->record_routes, rr2, -1);

    /* rfc3261: 12.1.1 UAS behavior (check sips in top most Record-Route) */
    if (it.pos==0 && rr2!=NULL && rr2->url!=NULL && rr2->url->scheme!=NULL && osip_strcasecmp(rr2->url->scheme, "sips")==0)
      snprintf(scheme, sizeof(scheme), "sips");

    rr = (osip_record_route_t *)osip_list_get_next(&it);
    route_found=1;
  }

  if (MSG_IS_BYE (request)) {
    return OSIP_SUCCESS;
  }

  if (route_found==0) {
    /* rfc3261: 12.1.1 UAS behavior (check sips in Contact if no Record-Route) */
    osip_contact_t *co = (osip_contact_t *) osip_list_get(&request->contacts, 0);
    if (co!=NULL && co->url!=NULL && co->url->scheme!=NULL && osip_strcasecmp(co->url->scheme, "sips")==0)
      snprintf(scheme, sizeof(scheme), "sips");
  }
  /* rfc3261: 12.1.1 UAS behavior (check sips in Request-URI) */
  if (request->req_uri->scheme!=NULL && osip_strcasecmp(request->req_uri->scheme, "sips")==0)
    snprintf(scheme, sizeof(scheme), "sips");

  /* special values to be replaced in transport layer (eXtl_*.c files) */
  if (request->to->url->username == NULL)
    snprintf (contact, 1000, "<%s:999.999.999.999:99999>", scheme);
  else {
    char *tmp2 = __osip_uri_escape_userinfo (request->to->url->username);

    snprintf (contact, 1000, "<%s:%[email protected]:99999>", scheme, tmp2);
    osip_free (tmp2);
  }

  {
    osip_via_t *via;

    via = (osip_via_t *) osip_list_get (&response->vias, 0);
    if (via == NULL || via->protocol == NULL)
      return OSIP_SYNTAXERROR;
    if (excontext->enable_outbound==1) {
      contact[strlen (contact) - 1] = '\0';
      strcat (contact, ";ob");
      strcat (contact, ">");
    }
    if (strlen (contact) + strlen (via->protocol) + strlen (";transport=>") < 1024 && 0 != osip_strcasecmp (via->protocol, "UDP")) {
      contact[strlen (contact) - 1] = '\0';
      strcat (contact, ";transport=");
      strcat (contact, via->protocol);
      strcat (contact, ">");
    }
    if (excontext->sip_instance[0] != 0 && strlen (contact) + 64 < 1024) {
      strcat(contact, ";+sip.instance=\"<urn:uuid:");
      strcat(contact, excontext->sip_instance);
      strcat(contact, ">\"");
    }
  }

  osip_message_set_contact (response, contact);

  if (excontext->default_contact_displayname[0]!='\0') {
    osip_contact_t *new_contact;
    osip_message_get_contact(response, 0, &new_contact);
    if (new_contact!=NULL) {
      new_contact->displayname = osip_strdup (excontext->default_contact_displayname);
    }
  }

  if (excontext->eXtl_transport._tl_update_contact!=NULL)
    excontext->eXtl_transport._tl_update_contact(excontext, response);
  return OSIP_SUCCESS;
}
Beispiel #20
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;
}
Beispiel #21
0
int
eXosip_call_send_request (int jid, osip_message_t * request)
{
  eXosip_dialog_t *jd = NULL;
  eXosip_call_t *jc = NULL;

  osip_transaction_t *transaction;
  osip_event_t *sipevent;

  int i;

  if (request == NULL)
    return OSIP_BADPARAMETER;
  if (jid <= 0)
    {
      osip_message_free (request);
      return OSIP_BADPARAMETER;
    }

  if (request->sip_method == NULL)
    {
      osip_message_free (request);
      return OSIP_BADPARAMETER;
    }

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

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

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

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

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

  osip_list_add (jd->d_out_trs, transaction, 0);

  sipevent = osip_new_outgoing_sipmessage (request);
  sipevent->transactionid = transaction->transactionid;

#ifndef MINISIZE
  osip_transaction_set_your_instance (transaction,
                                      __eXosip_new_jinfo (jc, jd, NULL, NULL));
#else
  osip_transaction_set_your_instance (transaction, __eXosip_new_jinfo (jc, jd));
#endif
  osip_transaction_add_event (transaction, sipevent);
  __eXosip_wakeup ();
  return OSIP_SUCCESS;
}
Beispiel #22
0
int GB_sipd_register_auth(GB_CONNECT_STATE *gb_cons, int flag)
{
	osip_message_t *reg = NULL;
	PRM_GB_SIPD_CFG gb_cfg;
	char from[GB_URI_MAX_LEN] = {0};
	char proxy[GB_URI_MAX_LEN] = {0};
	int ret;
	char *result = NULL;
	size_t length;
	char localip[20];
	char sipserver_ip[20] = {0};
	char *uri = NULL;
	osip_authorization_t *aut = NULL;
	
	SN_MEMSET(&gb_cfg, 0, sizeof(gb_cfg));
	
	GB_Get_GBCfg(&gb_cfg);

	SN_MEMSET(localip,0,sizeof(localip));
	SN_STRCPY(localip,sizeof(localip),GB_Get_LocalIP());
		
	SN_SPRINTF(sipserver_ip,sizeof(sipserver_ip),"%d.%d.%d.%d",
		gb_cfg.sipserver_ip[0],gb_cfg.sipserver_ip[1],gb_cfg.sipserver_ip[2],gb_cfg.sipserver_ip[3]);

	SN_SPRINTF(from, GB_URI_MAX_LEN, "sip:%s@%s", gb_cfg.deviceID, localip);
	SN_SPRINTF(proxy, GB_URI_MAX_LEN, "sip:%s@%s:%d", gb_cfg.sipserver_ID,sipserver_ip, gb_cfg.sipserver_port);

	if(flag == 0)  // 注册
	{
		ret = gb_generating_register(&reg, Transport_Str[gb_cons->transfer_protocol], from, proxy, NULL, gb_cfg.register_period, localip,gb_cfg.local_port, gb_cons->local_cseq);
	}
	else  //  注销
	{
		ret = gb_generating_register(&reg, Transport_Str[gb_cons->transfer_protocol], from, proxy, NULL, 0, localip,gb_cfg.local_port, gb_cons->local_cseq);
	}
		
	if (ret < 0)
	{
		osip_message_free (reg);
		return -1;
	}

	ret = osip_uri_to_str (reg->req_uri, &uri);
	if (ret != 0)
		return ret;
	
	ret = gb_create_authorization_header (gb_cons->wwwa, uri, ADMIN_NAME, (char *)gb_cfg.reg_pwd, NULL, &aut, "REGISTER", NULL, 0);

	osip_free (uri);
	if (ret != 0)
		return ret;

	if (aut != NULL) 
	{
		if (osip_strcasecmp (reg->sip_method, "REGISTER") == 0)
			osip_list_add (&reg->authorizations, aut, -1);
		else
			osip_list_add (&reg->proxy_authorizations, aut, -1);
		osip_message_force_update (reg);	
	}

	ret = osip_message_to_str(reg, &result, &length);
	if (ret == -1) 
	{
		printf("ERROR: failed while printing message!\n");
		osip_message_free (reg);
		return -1;
	}	
	gb_cons->local_cseq++;
	GB_SocketSendData(gb_cons->connfd,inet_ntoa(gb_cons->remoteAddr.sin_addr), ntohs(gb_cons->remoteAddr.sin_port), result, length, 0);
	SN_FREE(result);
	osip_message_free(reg);
	
	return 0;
}
Beispiel #23
0
/* 
   method is the type of request. ("INVITE", "REGISTER"...)
   to is the remote target URI
   transport is either "TCP" or "UDP" (by now, only UDP is implemented!)
*/
int
generating_request_out_of_dialog (osip_message_t ** dest, const char *method,
                                  const char *to, const char *transport,
                                  const char *from, const char *proxy)
{
  /* Section 8.1:
     A valid request contains at a minimum "To, From, Call-iD, Cseq,
     Max-Forwards and Via
   */
  int i;
  osip_message_t *request;
  char locip[65];
  int doing_register;
  char *register_callid_number = NULL;

  *dest = NULL;

  if (eXosip.eXtl == NULL)
    return OSIP_NO_NETWORK;

  /*guess the local ip since req uri is known */
  memset (locip, '\0', sizeof (locip));
  eXosip_guess_ip_for_via (eXosip.eXtl->proto_family, locip, 49);
  if (locip[0] == '\0')
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: no default interface defined\n"));
      return OSIP_NO_NETWORK;
    }

  i = osip_message_init (&request);
  if (i != 0)
    return i;

  /* prepare the request-line */
  osip_message_set_method (request, osip_strdup (method));
  osip_message_set_version (request, osip_strdup ("SIP/2.0"));
  osip_message_set_status_code (request, 0);
  osip_message_set_reason_phrase (request, NULL);

  doing_register = 0 == strcmp ("REGISTER", method);

  if (doing_register)
    {
      osip_uri_init (&(request->req_uri));
      i = osip_uri_parse (request->req_uri, proxy);
      if (i != 0)
        {
          osip_message_free (request);
          return i;
        }
      i = osip_message_set_to (request, from);
      if (i != 0 || request->to == NULL)
        {
          if (i >= 0)
            i = OSIP_SYNTAXERROR;
          osip_message_free (request);
          return i;
        }
  } else
    {
      /* in any cases except REGISTER: */
      i = osip_message_set_to (request, to);
      if (i != 0 || request->to == NULL)
        {
          if (i >= 0)
            i = OSIP_SYNTAXERROR;
          OSIP_TRACE (osip_trace
                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
                       "ERROR: callee address does not seems to be a sipurl: %s\n",
                       to));
          osip_message_free (request);
          return i;
        }

      /* REMOVE ALL URL PARAMETERS from to->url headers and add them as headers */
      if (request->to != NULL && request->to->url != NULL)
        {
          osip_uri_t *url = request->to->url;
          while (osip_list_size (&url->url_headers) > 0)
            {
              osip_uri_header_t *u_header;
              u_header = (osip_uri_param_t *) osip_list_get (&url->url_headers, 0);
              if (u_header == NULL)
                break;

              if (osip_strcasecmp (u_header->gname, "from") == 0)
                {
              } else if (osip_strcasecmp (u_header->gname, "to") == 0)
                {
              } else if (osip_strcasecmp (u_header->gname, "call-id") == 0)
                {
              } else if (osip_strcasecmp (u_header->gname, "cseq") == 0)
                {
              } else if (osip_strcasecmp (u_header->gname, "via") == 0)
                {
              } else if (osip_strcasecmp (u_header->gname, "contact") == 0)
                {
              } else
                osip_message_set_header (request, u_header->gname,
                                         u_header->gvalue);
              osip_list_remove (&url->url_headers, 0);
              osip_uri_param_free (u_header);
            }
        }

      if (proxy != NULL && proxy[0] != 0)
        {                       /* equal to a pre-existing route set */
          /* if the pre-existing route set contains a "lr" (compliance
             with bis-08) then the req_uri should contains the remote target
             URI */
          osip_uri_param_t *lr_param;
          osip_route_t *o_proxy;

          osip_route_init (&o_proxy);
          i = osip_route_parse (o_proxy, proxy);
          if (i != 0)
            {
              osip_route_free (o_proxy);
              osip_message_free (request);
              return i;
            }

          osip_uri_uparam_get_byname (o_proxy->url, "lr", &lr_param);
          if (lr_param != NULL) /* to is the remote target URI in this case! */
            {
              osip_uri_clone (request->to->url, &(request->req_uri));
              /* "[request] MUST includes a Route header field containing
                 the route set values in order." */
              osip_list_add (&request->routes, o_proxy, 0);
          } else
            /* if the first URI of route set does not contain "lr", the req_uri
               is set to the first uri of route set */
            {
              request->req_uri = o_proxy->url;
              o_proxy->url = NULL;
              osip_route_free (o_proxy);
              /* add the route set */
              /* "The UAC MUST add a route header field containing
                 the remainder of the route set values in order.
                 The UAC MUST then place the remote target URI into
                 the route header field as the last value
               */
              osip_message_set_route (request, to);
            }
      } else                    /* No route set (outbound proxy) is used */
        {
          /* The UAC must put the remote target URI (to field) in the req_uri */
          i = osip_uri_clone (request->to->url, &(request->req_uri));
          if (i != 0)
            {
              osip_message_free (request);
              return i;
            }
        }
    }

  /* set To and From */
  i = osip_message_set_from (request, from);
  if (i != 0 || request->from == NULL)
    {
      if (i >= 0)
        i = OSIP_SYNTAXERROR;
      osip_message_free (request);
      return i;
    }

  /* add a tag */
  osip_from_set_tag (request->from, osip_from_tag_new_random ());

  /* set the cseq and call_id header */
  {
    osip_call_id_t *callid;
    osip_cseq_t *cseq;
    char *num;
    char *cidrand;

    /* call-id is always the same for REGISTRATIONS */
    i = osip_call_id_init (&callid);
    if (i != 0)
      {
        osip_message_free (request);
        return i;
      }
    cidrand = osip_call_id_new_random ();
    osip_call_id_set_number (callid, cidrand);
    if (doing_register)
      register_callid_number = cidrand;

    request->call_id = callid;

    i = osip_cseq_init (&cseq);
    if (i != 0)
      {
        osip_message_free (request);
        return i;
      }
    num = osip_strdup (doing_register ? "1" : "20");
    osip_cseq_set_number (cseq, num);
    osip_cseq_set_method (cseq, osip_strdup (method));
    request->cseq = cseq;

    if (cseq->method == NULL || cseq->number == NULL)
      {
        osip_message_free (request);
        return OSIP_NOMEM;
      }
  }

  i = _eXosip_request_add_via (request, transport, locip);
  if (i != 0)
    {
      osip_message_free (request);
      return i;
    }

  /* always add the Max-Forward header */
  osip_message_set_max_forwards (request, "70");        /* a UA should start a request with 70 */

  if (0 == strcmp ("REGISTER", method))
    {
  } else if (0 == strcmp ("INFO", method))
    {
  } else if (0 == strcmp ("OPTIONS", method))
    {
      osip_message_set_accept (request, "application/sdp");
    }

  osip_message_set_user_agent (request, eXosip.user_agent);
  /*  else if ... */
  *dest = request;
  return OSIP_SUCCESS;
}
int
eXosip_insubscription_send_answer (int tid, int status, osip_message_t * answer)
{
    int i = -1;
    eXosip_dialog_t *jd = NULL;
    eXosip_notify_t *jn = NULL;
    osip_transaction_t *tr = NULL;
    osip_event_t *evt_answer;

    if (tid > 0)
    {
        _eXosip_insubscription_transaction_find (tid, &jn, &jd, &tr);
    }
    if (jd == NULL || tr == NULL || tr->orig_request == NULL
            || tr->orig_request->sip_method == NULL)
    {
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_ERROR, NULL,
                     "eXosip: No incoming subscription here?\n"));
        osip_message_free (answer);
        return -1;
    }

    if (answer == NULL)
    {
        if (0 == osip_strcasecmp (tr->orig_request->sip_method, "SUBSCRIBE"))
        {
            if (status >= 101 && status <= 199)
            {
            } else if (status >= 300 && status <= 699)
            {
            } else
            {
                OSIP_TRACE (osip_trace
                            (__FILE__, __LINE__, OSIP_ERROR, NULL,
                             "eXosip: Wrong parameter?\n"));
                return -1;
            }
        }
    }

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

    if (answer == NULL)
    {
        if (0 == osip_strcasecmp (tr->orig_request->sip_method, "SUBSCRIBE"))
        {
            if (status < 200)
                i = _eXosip_insubscription_answer_1xx (jn, jd, status);
            else
                i = _eXosip_insubscription_answer_3456xx (jn, jd, status);
            if (i != 0)
            {
                OSIP_TRACE (osip_trace
                            (__FILE__, __LINE__, OSIP_ERROR, NULL,
                             "eXosip: cannot send response!\n"));
                return -1;
            }
        } else
        {
            /* TODO */
            OSIP_TRACE (osip_trace
                        (__FILE__, __LINE__, OSIP_ERROR, NULL,
                         "eXosip: a response must be given!\n"));
            return -1;
        }
        return 0;
    } else
    {
        i = 0;
    }

    if (0 == osip_strcasecmp (tr->orig_request->sip_method, "SUBSCRIBE"))
    {
        if (MSG_IS_STATUS_1XX (answer))
        {
        } else if (MSG_IS_STATUS_2XX (answer))
        {
            eXosip_dialog_set_200ok (jd, answer);
            osip_dialog_set_state (jd->d_dialog, DIALOG_CONFIRMED);
        } else if (answer->status_code >= 300 && answer->status_code <= 699)
        {
            i = 0;
        } else
        {
            OSIP_TRACE (osip_trace
                        (__FILE__, __LINE__, OSIP_ERROR, NULL,
                         "eXosip: wrong status code (101<status<699)\n"));
            osip_message_free (answer);
            return -1;
        }
        if (i != 0)
        {
            osip_message_free (answer);
            return -1;
        }
    }

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

    osip_transaction_add_event (tr, evt_answer);
    eXosip_update ();
    __eXosip_wakeup ();
    return 0;
}
Beispiel #25
0
int
_eXosip_dialog_add_contact (osip_message_t * request, osip_message_t * answer)
{
  osip_via_t *via;
  osip_from_t *a_from;
  char *contact = NULL;
  char locip[65];
  char firewall_ip[65];
  char firewall_port[10];
  int len;

  if (eXosip.eXtl == NULL)
    return OSIP_NO_NETWORK;
  if (request == NULL)
    return OSIP_BADPARAMETER;

  if (eXosip.eXtl->tl_get_masquerade_contact != NULL)
    {
      eXosip.eXtl->tl_get_masquerade_contact (firewall_ip, sizeof (firewall_ip),
                                              firewall_port,
                                              sizeof (firewall_port));
    }

  /* search for topmost Via which indicate the transport protocol */
  via = (osip_via_t *) osip_list_get (&request->vias, 0);
  if (via == NULL || via->protocol == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: missing via header\n"));
      return OSIP_SYNTAXERROR;
    }

  if (answer == NULL)
    a_from = request->from;
  else
    a_from = answer->to;

  if (a_from == NULL || a_from->url == NULL)
    return OSIP_SYNTAXERROR;

  /*guess the local ip since req uri is known */
  memset (locip, '\0', sizeof (locip));

  if (a_from->url->username != NULL)
    len =
      2 + 4 + strlen (a_from->url->username) + 1 + 100 + 6 + 10 +
      strlen (eXosip.transport);
  else
    len = 2 + 4 + 100 + 6 + 10 + strlen (eXosip.transport);

  contact = (char *) osip_malloc (len + 1);
  if (contact == NULL)
    return OSIP_NOMEM;
  if (firewall_ip[0] != '\0')
    {
      char *c_address = request->req_uri->host;

      struct addrinfo *addrinfo;
      struct __eXosip_sockaddr addr;
      int i;

      i =
        eXosip_get_addrinfo (&addrinfo, request->req_uri->host, 5060, IPPROTO_TCP);
      if (i == 0)
        {
          memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
          eXosip_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))
        {
          memcpy (locip, firewall_ip, sizeof (locip));
        }
    }

  if (locip[0] == '\0')
    {
      eXosip_guess_ip_for_via (eXosip.eXtl->proto_family, locip, 49);
      if (locip[0] == '\0')
        {
          OSIP_TRACE (osip_trace
                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
                       "eXosip: no default interface defined\n"));
          return OSIP_NO_NETWORK;
        }
    }

  if (eXosip.eXtl->proto_family == AF_INET6)
    {
      if (a_from->url->username != NULL)
        snprintf (contact, len, "<sip:%s@[%s]:%s>", a_from->url->username,
                  locip, firewall_port);
      else
        snprintf (contact, len - strlen (eXosip.transport) - 10, "<sip:[%s]:%s>",
                  locip, firewall_port);
  } else
    {
      if (a_from->url->username != NULL)
        snprintf (contact, len, "<sip:%s@%s:%s>", a_from->url->username,
                  locip, firewall_port);
      else
        snprintf (contact, len - strlen (eXosip.transport) - 10, "<sip:%s:%s>",
                  locip, firewall_port);
    }
  if (osip_strcasecmp (eXosip.transport, "UDP") != 0)
    {
      contact[strlen (contact) - 1] = '\0';
      strcat (contact, ";transport=");
      strcat (contact, eXosip.transport);
      strcat (contact, ">");
    }
  osip_message_set_contact (request, contact);
  osip_free (contact);

  return OSIP_SUCCESS;
}
Beispiel #26
0
int
eXosip_call_build_prack (int tid, osip_message_t ** prack)
{
  eXosip_dialog_t *jd = NULL;
  eXosip_call_t *jc = NULL;
  osip_transaction_t *tr = NULL;

  osip_header_t *rseq;
  char *transport;
  int i;

  *prack = NULL;

  if (tid < 0)
    return OSIP_BADPARAMETER;

  if (tid > 0)
    {
      _eXosip_call_transaction_find (tid, &jc, &jd, &tr);
    }
  if (jc == NULL || jd == NULL || jd->d_dialog == NULL
      || tr == NULL || tr->orig_request == NULL
      || tr->orig_request->sip_method == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: No call here or no transaction for call\n"));
      return OSIP_NOTFOUND;
    }

  if (0 != osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
    return OSIP_BADPARAMETER;

  /* PRACK are only send in the PROCEEDING state */
  if (tr->state != ICT_PROCEEDING)
    return OSIP_WRONG_STATE;

  if (tr->orig_request->cseq == NULL
      || tr->orig_request->cseq->number == NULL
      || tr->orig_request->cseq->method == NULL)
    return OSIP_SYNTAXERROR;

  transport = NULL;
  if (tr != NULL && tr->orig_request != NULL)
    transport = _eXosip_transport_protocol (tr->orig_request);

  if (transport == NULL)
    i = _eXosip_build_request_within_dialog (prack, "PRACK", jd->d_dialog, "UDP");
  else
    i =
      _eXosip_build_request_within_dialog (prack, "PRACK", jd->d_dialog,
                                           transport);

  if (i != 0)
    return i;

  osip_message_header_get_byname (tr->last_response, "RSeq", 0, &rseq);
  if (rseq != NULL && rseq->hvalue != NULL)
    {
      char tmp[128];

      memset (tmp, '\0', sizeof (tmp));
      snprintf (tmp, 127, "%s %s %s", rseq->hvalue,
                tr->orig_request->cseq->number, tr->orig_request->cseq->method);
      osip_message_set_header (*prack, "RAck", tmp);
    }

  return OSIP_SUCCESS;
}
static int
_osip_message_to_str (osip_message_t * sip, char **dest, size_t * message_length, int sipfrag)
{
  size_t malloc_size;
  size_t total_length = 0;

  /* Added at SIPit day1 */
  char *start_of_bodies;
  char *content_length_to_modify = NULL;

  char *message;
  char *next;
  char *tmp;
  int pos;
  int i;
  char *boundary = NULL;

  malloc_size = SIP_MESSAGE_MAX_LENGTH;

  *dest = NULL;
  if (sip == NULL)
    return OSIP_BADPARAMETER;

  {
    if (1 == osip_message_get__property (sip)) {        /* message is already available in "message" */

      *dest = osip_malloc (sip->message_length + 1);
      if (*dest == NULL)
        return OSIP_NOMEM;
      memcpy (*dest, sip->message, sip->message_length);
      (*dest)[sip->message_length] = '\0';
      if (message_length != NULL)
        *message_length = sip->message_length;
      return OSIP_SUCCESS;
    }
    else {
      /* message should be rebuilt: delete the old one if exists. */
      osip_free (sip->message);
      sip->message = NULL;
    }
  }

  message = (char *) osip_malloc (SIP_MESSAGE_MAX_LENGTH);      /* ???? message could be > 4000  */
  if (message == NULL)
    return OSIP_NOMEM;
  *dest = message;

  /* add the first line of message */
  i = __osip_message_startline_to_str (sip, &tmp);
  if (i != 0) {
    if (!sipfrag) {
      osip_free (*dest);
      *dest = NULL;
      return i;
    }

    /* A start-line isn't required for message/sipfrag parts. */
  }
  else {
    message = osip_str_append (message, tmp);
    osip_free (tmp);
    message = osip_strn_append (message, CRLF, 2);
  }

  {
    struct to_str_table {
      char header_name[30];
      int header_length;
      osip_list_t *header_list;
      void *header_data;
      int (*to_str) (void *, char **);
    }
#ifndef MINISIZE
    table[25] =
#else
    table[15] =
#endif
    {
      {
      "Via: ", 5, NULL, NULL, (int (*)(void *, char **)) &osip_via_to_str}, {
      "Record-Route: ", 14, NULL, NULL, (int (*)(void *, char **)) &osip_record_route_to_str}, {
      "Route: ", 7, NULL, NULL, (int (*)(void *, char **)) &osip_route_to_str}, {
      "From: ", 6, NULL, NULL, (int (*)(void *, char **)) &osip_from_to_str}, {
      "To: ", 4, NULL, NULL, (int (*)(void *, char **)) &osip_to_to_str}, {
      "Call-ID: ", 9, NULL, NULL, (int (*)(void *, char **)) &osip_call_id_to_str}, {
      "CSeq: ", 6, NULL, NULL, (int (*)(void *, char **)) &osip_cseq_to_str}, {
      "Contact: ", 9, NULL, NULL, (int (*)(void *, char **)) &osip_contact_to_str}, {
      "Authorization: ", 15, NULL, NULL, (int (*)(void *, char **)) &osip_authorization_to_str}, {
      "WWW-Authenticate: ", 18, NULL, NULL, (int (*)(void *, char **)) &osip_www_authenticate_to_str}, {
      "Proxy-Authenticate: ", 20, NULL, NULL, (int (*)(void *, char **)) &osip_www_authenticate_to_str}, {
      "Proxy-Authorization: ", 21, NULL, NULL, (int (*)(void *, char **)) &osip_authorization_to_str}, {
      "Content-Type: ", 14, NULL, NULL, (int (*)(void *, char **)) &osip_content_type_to_str}, {
      "Mime-Version: ", 14, NULL, NULL, (int (*)(void *, char **)) &osip_content_length_to_str},
#ifndef MINISIZE
      {
      "Allow: ", 7, NULL, NULL, (int (*)(void *, char **)) &osip_allow_to_str}, {
      "Content-Encoding: ", 18, NULL, NULL, (int (*)(void *, char **)) &osip_content_encoding_to_str}, {
      "Call-Info: ", 11, NULL, NULL, (int (*)(void *, char **)) &osip_call_info_to_str}, {
      "Alert-Info: ", 12, NULL, NULL, (int (*)(void *, char **)) &osip_call_info_to_str}, {
      "Error-Info: ", 12, NULL, NULL, (int (*)(void *, char **)) &osip_call_info_to_str}, {
      "Accept: ", 8, NULL, NULL, (int (*)(void *, char **)) &osip_accept_to_str}, {
      "Accept-Encoding: ", 17, NULL, NULL, (int (*)(void *, char **)) &osip_accept_encoding_to_str}, {
      "Accept-Language: ", 17, NULL, NULL, (int (*)(void *, char **)) &osip_accept_language_to_str}, {
      "Authentication-Info: ", 21, NULL, NULL, (int (*)(void *, char **)) &osip_authentication_info_to_str}, {
      "Proxy-Authentication-Info: ", 27, NULL, NULL, (int (*)(void *, char **)) &osip_authentication_info_to_str},
#endif
      { {
      '\0'}, 0, NULL, NULL, NULL}
    };

    /* BEGIN: Added by l00183184, 2013/8/5   PN:DTS2013071906746 alg升级 */
    /* 判断list是否需要强制分为多行写 */
#ifndef MINISIZE
    char MultiLine[25] = {1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 
    0, 0, 1, 1, 1, 0, 0, 0, 0, 0};
#else
    char MultiLine[15] = {1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0};
#endif
    /* END:   Added by l00183184, 2013/8/5   PN:DTS2013071906746 alg升级 */

    table[0].header_list = &sip->vias;
    table[1].header_list = &sip->record_routes;
    table[2].header_list = &sip->routes;
    table[3].header_data = sip->from;
    table[4].header_data = sip->to;
    table[5].header_data = sip->call_id;
    table[6].header_data = sip->cseq;
    table[7].header_list = &sip->contacts;
    table[8].header_list = &sip->authorizations;
    table[9].header_list = &sip->www_authenticates;
    table[10].header_list = &sip->proxy_authenticates;
    table[11].header_list = &sip->proxy_authorizations;
    table[12].header_data = sip->content_type;
    table[13].header_data = sip->mime_version;
#ifndef MINISIZE
    table[14].header_list = &sip->allows;
    table[15].header_list = &sip->content_encodings;
    table[16].header_list = &sip->call_infos;
    table[17].header_list = &sip->alert_infos;
    table[18].header_list = &sip->error_infos;
    table[19].header_list = &sip->accepts;
    table[20].header_list = &sip->accept_encodings;
    table[21].header_list = &sip->accept_languages;
    table[22].header_list = &sip->authentication_infos;
    table[23].header_list = &sip->proxy_authentication_infos;
#endif

    pos = 0;
    while (table[pos].header_name[0] != '\0') {
      if (table[13].header_list == NULL)
        i = strcat_simple_header (dest, &malloc_size, &message, table[pos].header_data, table[pos].header_name, table[pos].header_length, ((int (*)(void *, char **))
                                                                                                                                           table[pos].to_str), &next);
      /* BEGIN: Modified by l00183184, 2013/8/5   PN:DTS2013071906746 alg升级 */
      /* 只有对应的routes等这几个头域的list分行写,其他的list合在一行 */
      /* 根据Rfc3261:
      Multiple header field rows with the same field-name MAY be present in
      a message if and only if the entire field-value for that header field
      is defined as a comma-separated list (that is, if follows the grammar
      defined in Section 7.3).*/
      if (1 == MultiLine[pos])
      {
          i = strcat_headers_one_per_line (dest, &malloc_size, &message, table[pos].header_list, table[pos].header_name, table[pos].header_length, ((int (*)(void *, char **))
                                                                                                                                                    table[pos].to_str), &next);
      }
      else
      {
          i = strcat_headers_all_on_one_line (dest, &malloc_size, &message, table[pos].header_list, table[pos].header_name, table[pos].header_length, ((int (*)(void *, char **))
                                                                                                                                                 table[pos].to_str), &next);
      }
      /* END:   Modified by l00183184, 2013/8/5   PN:DTS2013071906746 alg升级 */
      if (i != 0) {
        osip_free (*dest);
        *dest = NULL;
        return i;
      }
      message = next;

      pos++;
    }
  }

  pos = 0;
  while (!osip_list_eol (&sip->headers, pos)) {
    osip_header_t *header;
    size_t header_len = 0;

    header = (osip_header_t *) osip_list_get (&sip->headers, pos);
    i = osip_header_to_str (header, &tmp);
    if (i != 0) {
      osip_free (*dest);
      *dest = NULL;
      return i;
    }

    header_len = strlen (tmp);

    if (_osip_message_realloc (&message, dest, header_len + 3, &malloc_size) < 0) {
      osip_free (tmp);
      *dest = NULL;
      return OSIP_NOMEM;
    }

    message = osip_str_append (message, tmp);
    osip_free (tmp);
    message = osip_strn_append (message, CRLF, 2);

    pos++;
  }

  /* we have to create the body before adding the contentlength */
  /* add enough lenght for "Content-Length: " */

  if (_osip_message_realloc (&message, dest, 16, &malloc_size) < 0)
    return OSIP_NOMEM;

  if (sipfrag && osip_list_eol (&sip->bodies, 0)) {
    /* end of headers */
    osip_strncpy (message, CRLF, 2);
    message = message + 2;

    /* same remark as at the beginning of the method */
    sip->message_property = 1;
    sip->message = osip_strdup (*dest);
    sip->message_length = message - *dest;
    if (message_length != NULL)
      *message_length = message - *dest;

    return OSIP_SUCCESS;        /* it's all done */
  }

  osip_strncpy (message, "Content-Length: ", 16);
  message = message + 16;

  /* SIPit Day1
     ALWAYS RECALCULATE?
     if (sip->contentlength!=NULL)
     {
     i = osip_content_length_to_str(sip->contentlength, &tmp);
     if (i!=0) {
     osip_free(*dest);
     *dest = NULL;
     return i;
     }
     osip_strncpy(message,tmp,strlen(tmp));
     osip_free(tmp);
     }
     else
     { */
  if (osip_list_eol (&sip->bodies, 0))  /* no body */
    message = osip_strn_append (message, "0", 1);
  else {
    /* BUG: p130 (rfc2543bis-04)
       "No SP after last token or quoted string"

       In fact, if extra spaces exist: the stack can't be used
       to make user-agent that wants to make authentication...
       This should be changed...
     */

    content_length_to_modify = message;
    message = osip_str_append (message, "     ");
  }
  /*  } */

  message = osip_strn_append (message, CRLF, 2);


  /* end of headers */
  message = osip_strn_append (message, CRLF, 2);

  start_of_bodies = message;
  total_length = start_of_bodies - *dest;

  if (osip_list_eol (&sip->bodies, 0)) {
    /* same remark as at the beginning of the method */
    sip->message_property = 1;
    sip->message = osip_strdup (*dest);
    sip->message_length = total_length;
    if (message_length != NULL)
      *message_length = total_length;

    return OSIP_SUCCESS;        /* it's all done */
  }

  if (sip->mime_version != NULL && sip->content_type && sip->content_type->type && !osip_strcasecmp (sip->content_type->type, "multipart")) {
    osip_generic_param_t *ct_param = NULL;

    /* find the boundary */
    i = osip_generic_param_get_byname (&sip->content_type->gen_params, "boundary", &ct_param);
    if ((i >= 0) && ct_param && ct_param->gvalue) {
      size_t len = strlen (ct_param->gvalue);

      if (len > MIME_MAX_BOUNDARY_LEN) {
        osip_free (*dest);
        *dest = NULL;
        return OSIP_SYNTAXERROR;
      }

      boundary = osip_malloc (len + 5);
      if (boundary == NULL) {
        osip_free (*dest);
        *dest = NULL;
        return OSIP_NOMEM;
      }

      osip_strncpy (boundary, CRLF, 2);
      osip_strncpy (boundary + 2, "--", 2);

      if (ct_param->gvalue[0] == '"' && ct_param->gvalue[len - 1] == '"')
        osip_strncpy (boundary + 4, ct_param->gvalue + 1, len - 2);
      else
        osip_strncpy (boundary + 4, ct_param->gvalue, len);
    }
  }

  pos = 0;
  while (!osip_list_eol (&sip->bodies, pos)) {
    osip_body_t *body;
    size_t body_length;

    body = (osip_body_t *) osip_list_get (&sip->bodies, pos);

    if (boundary) {
      /* Needs at most 77 bytes,
         last realloc allocate at least 100 bytes extra */
      message = osip_str_append (message, boundary);
      message = osip_strn_append (message, CRLF, 2);
    }

    i = osip_body_to_str (body, &tmp, &body_length);
    if (i != 0) {
      osip_free (*dest);
      *dest = NULL;
      if (boundary)
        osip_free (boundary);
      return i;
    }

    if (malloc_size < message - *dest + 100 + body_length) {
      size_t size = message - *dest;
      int offset_of_body;
      int offset_content_length_to_modify = 0;

      offset_of_body = (int) (start_of_bodies - *dest);
      if (content_length_to_modify != NULL)
        offset_content_length_to_modify = (int) (content_length_to_modify - *dest);
      malloc_size = message - *dest + body_length + 100;
      *dest = osip_realloc (*dest, malloc_size);
      if (*dest == NULL) {
        osip_free (tmp);        /* fixed 09/Jun/2005 */
        if (boundary)
          osip_free (boundary);
        return OSIP_NOMEM;
      }
      start_of_bodies = *dest + offset_of_body;
      if (content_length_to_modify != NULL)
        content_length_to_modify = *dest + offset_content_length_to_modify;
      message = *dest + size;
    }

    memcpy (message, tmp, body_length);
    message[body_length] = '\0';
    osip_free (tmp);
    message = message + body_length;

    pos++;
  }

  if (boundary) {
    /* Needs at most 79 bytes,
       last realloc allocate at least 100 bytes extra */
    message = osip_str_append (message, boundary);
    message = osip_strn_append (message, "--", 2);
    message = osip_strn_append (message, CRLF, 2);

    osip_free (boundary);
    boundary = NULL;
  }

  if (content_length_to_modify == NULL) {
    osip_free (*dest);
    *dest = NULL;
    return OSIP_SYNTAXERROR;
  }

  /* we NOW have the length of bodies: */
  {
    size_t size = message - start_of_bodies;
    char tmp2[15];

    total_length += size;
    snprintf (tmp2, 15, "%i", (int) size);
    /* do not use osip_strncpy here! */
    strncpy (content_length_to_modify + 5 - strlen (tmp2), tmp2, strlen (tmp2));
  }

  /* same remark as at the beginning of the method */
  sip->message_property = 1;
  sip->message = osip_malloc (total_length + 1);
  if (sip->message != NULL) {
    memcpy (sip->message, *dest, total_length);
    sip->message[total_length] = '\0';
    sip->message_length = total_length;
    if (message_length != NULL)
      *message_length = total_length;
  }
  return OSIP_SUCCESS;
}
Beispiel #28
0
int
eXosip_call_send_prack (int tid, osip_message_t * prack)
{
  eXosip_dialog_t *jd = NULL;
  eXosip_call_t *jc = NULL;
  osip_transaction_t *tr = NULL;

  osip_event_t *sipevent;
  int i;

  if (tid < 0)
    return OSIP_BADPARAMETER;
  if (prack == NULL)
    return OSIP_BADPARAMETER;

  if (tid > 0)
    {
      _eXosip_call_transaction_find (tid, &jc, &jd, &tr);
    }
  if (jc == NULL || jd == NULL || jd->d_dialog == NULL
      || tr == NULL || tr->orig_request == NULL
      || tr->orig_request->sip_method == NULL)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: No call here or no transaction for call\n"));
      osip_message_free (prack);
      return OSIP_NOTFOUND;
    }

  if (0 != osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
    {
      osip_message_free (prack);
      return OSIP_BADPARAMETER;
    }

  /* PRACK are only send in the PROCEEDING state */
  if (tr->state != ICT_PROCEEDING)
    {
      osip_message_free (prack);
      return OSIP_WRONG_STATE;
    }

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

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

  jd->d_mincseq++;

  osip_list_add (jd->d_out_trs, tr, 0);

  sipevent = osip_new_outgoing_sipmessage (prack);
  sipevent->transactionid = tr->transactionid;

#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_wakeup ();
  return OSIP_SUCCESS;
}
Beispiel #29
0
void
nict_snd_request (osip_transaction_t * nict, osip_event_t * evt)
{
  int i;
  osip_t *osip = (osip_t *) nict->config;

  /* Here we have ict->orig_request == NULL */
  nict->orig_request = evt->sip;

  i = osip->cb_send_message (nict, evt->sip, nict->nict_context->destination, nict->nict_context->port, nict->out_socket);

  if (i >= 0) {
    /* invoke the right callback! */
    if (MSG_IS_REGISTER (evt->sip))
      __osip_message_callback (OSIP_NICT_REGISTER_SENT, nict, nict->orig_request);
    else if (MSG_IS_BYE (evt->sip))
      __osip_message_callback (OSIP_NICT_BYE_SENT, nict, nict->orig_request);
    else if (MSG_IS_OPTIONS (evt->sip))
      __osip_message_callback (OSIP_NICT_OPTIONS_SENT, nict, nict->orig_request);
    else if (MSG_IS_INFO (evt->sip))
      __osip_message_callback (OSIP_NICT_INFO_SENT, nict, nict->orig_request);
    else if (MSG_IS_CANCEL (evt->sip))
      __osip_message_callback (OSIP_NICT_CANCEL_SENT, nict, nict->orig_request);
    else if (MSG_IS_NOTIFY (evt->sip))
      __osip_message_callback (OSIP_NICT_NOTIFY_SENT, nict, nict->orig_request);
    else if (MSG_IS_SUBSCRIBE (evt->sip))
      __osip_message_callback (OSIP_NICT_SUBSCRIBE_SENT, nict, nict->orig_request);
    else
      __osip_message_callback (OSIP_NICT_UNKNOWN_REQUEST_SENT, nict, nict->orig_request);
#ifndef USE_BLOCKINGSOCKET
    /*
       stop timer E in reliable transport - non blocking socket: 
       the message was just sent
     */
    {
      osip_via_t *via;
      char *proto;
      int k;
      k = osip_message_get_via (nict->orig_request, 0, &via);   /* get top via */
      if (k < 0) {
        nict_handle_transport_error (nict, -1);
        return;
      }
      proto = via_get_protocol (via);
      if (proto == NULL) {
        nict_handle_transport_error (nict, -1);
        return;
      }
      if (i == 0) {               /* but message was really sent */
        if (osip_strcasecmp (proto, "TCP") != 0 && osip_strcasecmp (proto, "TLS") != 0 && osip_strcasecmp (proto, "SCTP") != 0) {
        }
        else {                    /* reliable protocol is used: */
          nict->nict_context->timer_e_length = -1;        /* E is not ACTIVE */
          nict->nict_context->timer_e_start.tv_sec = -1;
        }
      } else {
        if (osip_strcasecmp (proto, "TCP") != 0 && osip_strcasecmp (proto, "TLS") != 0 && osip_strcasecmp (proto, "SCTP") != 0) {
        }
        else {                    /* reliable protocol is used: */
          nict->nict_context->timer_e_length = DEFAULT_T1_TCP_PROGRESS;
        }
      }
    }
#endif
    if (nict->nict_context->timer_e_length > 0) {
      osip_gettimeofday (&nict->nict_context->timer_e_start, NULL);
      add_gettimeofday (&nict->nict_context->timer_e_start, nict->nict_context->timer_e_length);
    }
    __osip_transaction_set_state (nict, NICT_TRYING);
  }
  else {
    nict_handle_transport_error (nict, i);
  }
}
Beispiel #30
0
int
_eXosip_complete_answer_that_establish_a_dialog (struct eXosip_t *excontext, osip_message_t * response, osip_message_t * request)
{
  int i;
  int pos = 0;
  char contact[1024];
  char locip[65];
  char firewall_ip[65];
  char firewall_port[10];

  firewall_ip[0] = '\0';
  firewall_port[0] = '\0';
  if (excontext->eXtl->tl_get_masquerade_contact != NULL) {
    excontext->eXtl->tl_get_masquerade_contact (excontext, firewall_ip, sizeof (firewall_ip), firewall_port, sizeof (firewall_port));
  }

  /* 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 i;
    osip_list_add (&response->record_routes, rr2, -1);
    pos++;
  }

  memset (locip, '\0', sizeof (locip));
  _eXosip_guess_ip_for_via (excontext, excontext->eXtl->proto_family, locip, 49);

  if (request->to->url->username == NULL)
    snprintf (contact, 1000, "<sip:%s:%s>", locip, firewall_port);
  else {
    char *tmp2 = __osip_uri_escape_userinfo (request->to->url->username);

    snprintf (contact, 1000, "<sip:%s@%s:%s>", tmp2, locip, firewall_port);
    osip_free (tmp2);
  }
  if (firewall_ip[0] != '\0') {
#ifdef USE_LOCALIP_WITH_LOCALPROXY      /* disable this code for local testing because it adds an extra DNS */
    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 (excontext, &addrinfo, con->url->host, 5060, IPPROTO_UDP);
      if (i == 0) {
        memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
        _eXosip_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>", firewall_ip, firewall_port);
        else {
          char *tmp2 = __osip_uri_escape_userinfo (request->to->url->username);

          snprintf (contact, 1000, "<sip:%s@%s:%s>", tmp2, firewall_ip, firewall_port);
          osip_free (tmp2);
        }
      }
    }
#else
    if (request->to->url->username == NULL)
      snprintf (contact, 1000, "<sip:%s:%s>", firewall_ip, firewall_port);
    else {
      char *tmp2 = __osip_uri_escape_userinfo (request->to->url->username);

      snprintf (contact, 1000, "<sip:%s@%s:%s>", tmp2, firewall_ip, firewall_port);
      osip_free (tmp2);
    }
#endif
  }

  {
    osip_via_t *via;

    via = (osip_via_t *) osip_list_get (&response->vias, 0);
    if (via == NULL || via->protocol == NULL)
      return OSIP_SYNTAXERROR;
    if (strlen (contact) + strlen (via->protocol) + strlen (";transport=>") < 1024 && 0 != osip_strcasecmp (via->protocol, "UDP")) {
      contact[strlen (contact) - 1] = '\0';
      strcat (contact, ";transport=");
      strcat (contact, via->protocol);
      strcat (contact, ">");
    }
  }

  osip_message_set_contact (response, contact);

  return OSIP_SUCCESS;
}