Пример #1
0
/*
 * SIP_CALCULATE_BRANCH
 *
 * Calculates a branch parameter according to RFC3261 section 16.11
 *
 * The returned 'id' will be HASHHEXLEN + strlen(magic_cookie)
 * characters (32 + 7) long. The caller must supply at least this
 * amount of space in 'id'.
 *
 * RETURNS
 *	STS_SUCCESS on success
 *	STS_FAILURE on error
 */
int  sip_calculate_branch_id (sip_ticket_t *ticket, char *id) {
/* RFC3261 section 16.11 recommends the following procedure:
 *   The stateless proxy MAY use any technique it likes to guarantee
 *   uniqueness of its branch IDs across transactions.  However, the
 *   following procedure is RECOMMENDED.  The proxy examines the
 *   branch ID in the topmost Via header field of the received
 *   request.  If it begins with the magic cookie, the first
 *   component of the branch ID of the outgoing request is computed
 *   as a hash of the received branch ID.  Otherwise, the first
 *   component of the branch ID is computed as a hash of the topmost
 *   Via, the tag in the To header field, the tag in the From header
 *   field, the Call-ID header field, the CSeq number (but not
 *   method), and the Request-URI from the received request.  One of
 *   these fields will always vary across two different
 *   transactions.
 *
 * The branch value will consist of:
 * - magic cookie "z9hG4bK"
 * - 1st part (unique calculated ID
 * - 2nd part (value for loop detection) <<- not yet used by siproxd
 */
   osip_message_t *sip_msg=ticket->sipmsg;
   static char *magic_cookie="z9hG4bK";
   osip_via_t *via;
   osip_uri_param_t *param=NULL;
   osip_call_id_t *call_id=NULL;
   HASHHEX hashstring;

   hashstring[0]='\0';

   /*
    * Examine topmost via and look for a magic cookie.
    * If it is there, I use THIS branch parameter as input for
    * our hash calculation
    */
   via = osip_list_get (sip_msg->vias, 0);
   if (via == NULL) {
      ERROR("have a SIP message without any via header");
      return STS_FAILURE;
   }

   param=NULL;
   osip_via_param_get_byname(via, "branch", &param);
   if (param && param->gvalue) {
      DEBUGC(DBCLASS_BABBLE, "looking for magic cookie [%s]",param->gvalue);
      if (strncmp(param->gvalue, magic_cookie,
                  strlen(magic_cookie))==0) {
         /* calculate MD5 hash */
         MD5_CTX Md5Ctx;
         HASH HA1;

         MD5Init(&Md5Ctx);
         MD5Update(&Md5Ctx, param->gvalue,
                   strlen(param->gvalue));
         MD5Final(HA1, &Md5Ctx);
         CvtHex(HA1, hashstring);

         DEBUGC(DBCLASS_BABBLE, "existing branch -> branch hash [%s]",
                hashstring);
      }
   }

   /*
    * If I don't have a branch parameter in the existing topmost via,
    * then I need:
    *   - the topmost via
    *   - the tag in the To header field
    *   - the tag in the From header field
    *   - the Call-ID header field
    *   - the CSeq number (but not method)
    *   - the Request-URI from the received request
    */
   if (hashstring[0] == '\0') {
      /* calculate MD5 hash */
      MD5_CTX Md5Ctx;
      HASH HA1;
      char *tmp;

      MD5Init(&Md5Ctx);

      /* topmost via */
      osip_via_to_str(via, &tmp);
      if (tmp) {
         MD5Update(&Md5Ctx, tmp, strlen(tmp));
         osip_free(tmp);
      }
     
      /* Tag in To header */
      osip_to_get_tag(sip_msg->to, &param);
      if (param && param->gvalue) {
         MD5Update(&Md5Ctx, param->gvalue, strlen(param->gvalue));
      }

      /* Tag in From header */
      osip_from_get_tag(sip_msg->from, &param);
      if (param && param->gvalue) {
         MD5Update(&Md5Ctx, param->gvalue, strlen(param->gvalue));
      }

      /* Call-ID */
      call_id = osip_message_get_call_id(sip_msg);
      osip_call_id_to_str(call_id, &tmp);
      if (tmp) {
         MD5Update(&Md5Ctx, tmp, strlen(tmp));
         osip_free(tmp);
      }

      /* CSeq number (but not method) */
      tmp = osip_cseq_get_number(sip_msg->cseq);
      if (tmp) {
         MD5Update(&Md5Ctx, tmp, strlen(tmp));
      }
 
      /* Request URI */
      osip_uri_to_str(sip_msg->req_uri, &tmp);
      if (tmp) {
         MD5Update(&Md5Ctx, tmp, strlen(tmp));
         osip_free(tmp);
      }

      MD5Final(HA1, &Md5Ctx);
      CvtHex(HA1, hashstring);

      DEBUGC(DBCLASS_BABBLE, "non-existing branch -> branch hash [%s]",
             hashstring);
   }

   /* include the magic cookie */
   sprintf(id, "%s%s", magic_cookie, hashstring);

   return STS_SUCCESS;
}
Пример #2
0
/* returns -1 on error. */
int osip_record_route_to_str(const osip_record_route_t * record_route, char **dest)
{
	char *url;
	char *buf;
	int i;
	size_t len;

	*dest = NULL;
	if ((record_route == NULL) || (record_route->url == NULL))
		return OSIP_BADPARAMETER;

	i = osip_uri_to_str(record_route->url, &url);
	if (i != 0)
		return i;

	if (record_route->displayname == NULL)
		len = strlen(url) + 5;
	else
		len = strlen(url) + strlen(record_route->displayname) + 5;

	buf = (char *) osip_malloc(len);
	if (buf == NULL) {
		osip_free(url);
		return OSIP_NOMEM;
	}

	/* route and record-route always use brackets */
	if (record_route->displayname != NULL)
		sprintf(buf, "%s <%s>", record_route->displayname, url);
	else
		sprintf(buf, "<%s>", url);
	osip_free(url);

	{
		int pos = 0;
		osip_generic_param_t *u_param;
		size_t plen;
		char *tmp;

		while (!osip_list_eol(&record_route->gen_params, pos)) {
			u_param =
				(osip_generic_param_t *) osip_list_get(&record_route->gen_params,
													   pos);

			if (u_param->gvalue == NULL)
				plen = strlen(u_param->gname) + 2;
			else
				plen = strlen(u_param->gname) + strlen(u_param->gvalue) + 3;
			len = len + plen;
			buf = (char *) osip_realloc(buf, len);
			tmp = buf;
			tmp = tmp + strlen(tmp);
			if (u_param->gvalue == NULL)
				sprintf(tmp, ";%s", u_param->gname);
			else
				sprintf(tmp, ";%s=%s", u_param->gname, u_param->gvalue);
			pos++;
		}
	}
	*dest = buf;
	return OSIP_SUCCESS;
}
Пример #3
0
void
nist_rcv_request (osip_transaction_t * nist, osip_event_t * evt)
{
  int i;
  osip_t *osip = (osip_t *) nist->config;

  if (nist->state == NIST_PRE_TRYING)	/* announce new REQUEST */
    {
      /* Here we have ist->orig_request == NULL */
      nist->orig_request = evt->sip;

      if (MSG_IS_REGISTER (evt->sip))
	__osip_message_callback (OSIP_NIST_REGISTER_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_BYE (evt->sip))
	__osip_message_callback (OSIP_NIST_BYE_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_OPTIONS (evt->sip))
	__osip_message_callback (OSIP_NIST_OPTIONS_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_INFO (evt->sip))
	__osip_message_callback (OSIP_NIST_INFO_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_CANCEL (evt->sip))
	__osip_message_callback (OSIP_NIST_CANCEL_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_NOTIFY (evt->sip))
	__osip_message_callback (OSIP_NIST_NOTIFY_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_SUBSCRIBE (evt->sip))
	__osip_message_callback (OSIP_NIST_SUBSCRIBE_RECEIVED, nist,
			   nist->orig_request);
      else
	__osip_message_callback (OSIP_NIST_UNKNOWN_REQUEST_RECEIVED, nist,
			   nist->orig_request);
    }
  else				/* NIST_PROCEEDING or NIST_COMPLETED */
    {
      /* delete retransmission */
      osip_message_free (evt->sip);

      __osip_message_callback (OSIP_NIST_REQUEST_RECEIVED_AGAIN, nist,
			 nist->orig_request);
      if (nist->last_response != NULL)	/* retransmit last response */
	{
	  osip_via_t *via;

	  via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0);
	  if (via)
	    {
	      char *host;
	      int port;
	      osip_generic_param_t *maddr;
	      osip_generic_param_t *received;
	      osip_generic_param_t *rport;
	      osip_via_param_get_byname (via, "maddr", &maddr);
	      osip_via_param_get_byname (via, "received", &received);
	      osip_via_param_get_byname (via, "rport", &rport);
	      /* 1: user should not use the provided information
	         (host and port) if they are using a reliable
	         transport. Instead, they should use the already
	         open socket attached to this transaction. */
	      /* 2: check maddr and multicast usage */
	      if (maddr != NULL)
		host = maddr->gvalue;
	      /* we should check if this is a multicast address and use
	         set the "ttl" in this case. (this must be done in the
	         UDP message (not at the SIP layer) */
	      else if (received != NULL)
		host = received->gvalue;
	      else
		host = via->host;

	      if (rport == NULL || rport->gvalue == NULL)
		{
		  if (via->port != NULL)
		    port = osip_atoi (via->port);
		  else
		    port = 5060;
		}
	      else
		port = osip_atoi (rport->gvalue);

	      i = osip->cb_send_message (nist, nist->last_response, host,
					 port, nist->out_socket);
	    }
	  else
	    i = -1;
	  if (i != 0)
	    {
              nist_handle_transport_error (nist, i);
	      return;
	    }
	  else
	    {
	      if (MSG_IS_STATUS_1XX (nist->last_response))
		__osip_message_callback (OSIP_NIST_STATUS_1XX_SENT, nist,
				   nist->last_response);
	      else if (MSG_IS_STATUS_2XX (nist->last_response))
		__osip_message_callback (OSIP_NIST_STATUS_2XX_SENT_AGAIN, nist,
				   nist->last_response);
	      else
		__osip_message_callback (OSIP_NIST_STATUS_3456XX_SENT_AGAIN, nist,
				   nist->last_response);
	      return;
	    }
	}
      /* we are already in the proper state */
      return;
    }

  /* we come here only if it was the first REQUEST received */
  __osip_transaction_set_state (nist, NIST_TRYING);
}
Пример #4
0
/* returns -1 on error. */
int
osip_from_to_str (const osip_from_t * from, char **dest)
{
  char *url;
  char *buf;
  int i;
  size_t len;

  *dest = NULL;
  if ((from == NULL) || (from->url == NULL))
    return -1;

  i = osip_uri_to_str (from->url, &url);
  if (i != 0)
    return -1;

  if (from->displayname == NULL)
    len = strlen (url) + 5;
  else
    len = strlen (url) + strlen (from->displayname) + 5;

  buf = (char *) osip_malloc (len);
  if (buf == NULL)
    {
      osip_free (url);
      return -1;
    }

  if (from->displayname != NULL)
    sprintf (buf, "%s <%s>", from->displayname, url);
  else
    /* from rfc2543bis-04: for authentication related issue!
       "The To and From header fields always include the < and >
       delimiters even if the display-name is empty." */
    sprintf (buf, "<%s>", url);
  osip_free (url);

  {
    int pos = 0;
    osip_generic_param_t *u_param;
    size_t plen;
    char *tmp;

    while (!osip_list_eol (&from->gen_params, pos))
      {
        u_param = (osip_generic_param_t *) osip_list_get (&from->gen_params, pos);

        if (u_param->gvalue == NULL)
          plen = strlen (u_param->gname) + 2;
        else
          plen = strlen (u_param->gname) + strlen (u_param->gvalue) + 3;
        len = len + plen;
        buf = (char *) osip_realloc (buf, len);
        tmp = buf;
        tmp = tmp + strlen (tmp);
        if (u_param->gvalue == NULL)
          sprintf (tmp, ";%s", u_param->gname);
        else
          sprintf (tmp, ";%s=%s", u_param->gname, u_param->gvalue);
        pos++;
      }
  }
  *dest = buf;
  return 0;
}
Пример #5
0
/* returns null on error. */
int
osip_via_to_str (const osip_via_t * via, char **dest)
{
  char *buf;
  size_t len;
  size_t plen;
  char *tmp;

  *dest = NULL;
  if ((via == NULL) || (via->host == NULL)
      || (via->version == NULL) || (via->protocol == NULL))
    return -1;

  len = strlen (via->version) + 1 + strlen (via->protocol) + 1 + 3 + 2;	/* sip/xxx/xxx */
  len = len + strlen (via->host) + 3 + 1;
  if (via->port != NULL)
    len = len + strlen (via->port) + 2;

  buf = (char *) osip_malloc (len);
  if (buf == NULL)
    return -1;

  if (strchr (via->host, ':') != NULL)
    {
      if (via->port == NULL)
	sprintf (buf, "SIP/%s/%s [%s]", via->version, via->protocol,
		 via->host);
      else
	sprintf (buf, "SIP/%s/%s [%s]:%s", via->version, via->protocol,
		 via->host, via->port);
    }
  else
    {
      if (via->port == NULL)
	sprintf (buf, "SIP/%s/%s %s", via->version, via->protocol, via->host);
      else
	sprintf (buf, "SIP/%s/%s %s:%s", via->version, via->protocol,
		 via->host, via->port);
    }



  {
    int pos = 0;
    osip_generic_param_t *u_param;

    while (!osip_list_eol (via->via_params, pos))
      {
	u_param =
	  (osip_generic_param_t *) osip_list_get (via->via_params, pos);

	if (u_param->gvalue == NULL)
	  plen = strlen (u_param->gname) + 2;
	else
	  plen = strlen (u_param->gname) + strlen (u_param->gvalue) + 3;
	len = len + plen;
	buf = (char *) realloc (buf, len);
	tmp = buf;
	tmp = tmp + strlen (tmp);
	if (u_param->gvalue == NULL)
	  sprintf (tmp, ";%s", u_param->gname);
	else
	  sprintf (tmp, ";%s=%s", u_param->gname, u_param->gvalue);
	pos++;
      }
  }

  if (via->comment != NULL)
    {
      len = len + strlen (via->comment) + 4;
      buf = (char *) realloc (buf, len);
      tmp = buf;
      tmp = tmp + strlen (tmp);
      sprintf (tmp, " (%s)", via->comment);
    }
  *dest = buf;
  return 0;
}
Пример #6
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 -1;
  if (jd != NULL)
    {
      if (jd->d_out_trs == NULL)
        return -1;
    }
  if (out_tr == NULL
      || out_tr->orig_request == NULL || out_tr->last_response == NULL)
    return -1;

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

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

  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 -1;
	}
      
      /* 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);
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
                   "eXosip: unsupported protocol\n"));
      return -1;
    }

  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 -1;
    }

  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 0;
}
Пример #7
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);
				    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);
				    snprintf(co->url->port, 9, "%i", ainfo->nat_port);
				}
			}
	    }
	}
  }

  return 0;
}
Пример #8
0
        void SIPBuilder::BeenInvited( osip_message_t* msg, string port,char** rtmsg,
                size_t *rtlen, int*state, struct DialogInfo &dlg_info)
        {
            string uac_ip = _local_ip_str_;
            string uac_listen_port_str = _local_port_str_;
            string local_dev_name = _dev_name_;

            string head_line("SIP/2.0 200 OK\r\n");

            osip_via_t *via;
            char* via_c = NULL; 
            if( !osip_list_eol (&msg->vias, 0))
            {
                via = (osip_via_t *) osip_list_get (&msg->vias, 0);
                osip_via_to_str( via, &via_c);
            }else{
                *state = -1;
                return;
            }
            string via_header(via_c);
            via_header = string("Via: ")+via_header+string("\r\n");
            
            char* from_tag_c;
            osip_from_to_str( msg->from, &from_tag_c );
            string from_header(from_tag_c);
            from_header = string("From: ")+from_header+string("\r\n");

            char* to_tag_c;
            osip_to_to_str( msg->to, &to_tag_c );
            string to_header(to_tag_c);
            string to_tag_num = _RandomNum();
            to_header = to_header + ";tag="+to_tag_num;
            to_header = string("To: ")+to_header+string("\r\n");
            dlg_info.to_tag_num = to_tag_num;

            string contact_header;
            stringstream stream_contact_header;
            stream_contact_header<<"Contact: <sip:" << local_dev_name << "@" << uac_ip << ":"<< uac_listen_port_str<<">\r\n";
            contact_header = stream_contact_header.str();

            string call_id_num = string(msg->call_id->number);
            string call_header = string("Call-ID: ")+call_id_num+("\r\n");

            string cseq_num = string(msg->cseq->number);
            string cseq_header = string("Cseq: ")+cseq_num+string(" INVITE\r\n");
            string content_type_header = "Content-Type: APPLICATION/SDP\r\n";

            string forwords = string("Max-Forwards: 70\r\n");
            string expires = string("Expires: 3000\r\n");
            string sdp_msg = _sdp_builder_.toString( string("##2015"), port);
            stringstream sdp_msg_length; 
            sdp_msg_length<< sdp_msg.length();
            string contentlenth = string("Content-Length: ")+sdp_msg_length.str()+string("\r\n");
            string cflr = string("\r\n");

            string sip_msg_str = head_line + via_header + to_header + from_header
                + call_header + cseq_header  + contact_header  +  content_type_header + 
                forwords + expires + contentlenth + cflr + sdp_msg;
#ifdef DEBUG
            cout<<"check Been Invite:"<<endl;
            cout<<sip_msg_str<<endl;
#endif
            size_t sip_len = sip_msg_str.length();
            char* sip_msg_c = (char*)malloc(sizeof(char)* sip_len);
            memcpy( sip_msg_c, sip_msg_str.c_str(), sip_len);
            *rtmsg = sip_msg_c;
            *rtlen = sip_len;
            /*send 200ok, wait ack*/
            *state = 0;
            return;
        }
Пример #9
0
int
test_message (char *msg, size_t len, int verbose, int clone)
{
  osip_message_t *sip;

  {
    char *result;

    /* int j=10000; */
    int j = 1;

    if (verbose)
      fprintf (stdout, "Trying %i sequentials calls to osip_message_init(), osip_message_parse() and osip_message_free()\n", j);
    while (j != 0) {
      j--;
      osip_message_init (&sip);
      if (osip_message_parse (sip, msg, len) != 0) {
        fprintf (stdout, "ERROR: failed while parsing!\n");
        osip_message_free (sip);
        return -1;
      }
      osip_message_free (sip);
    }

    osip_message_init (&sip);
    if (osip_message_parse (sip, msg, len) != 0) {
      fprintf (stdout, "ERROR: failed while parsing!\n");
      osip_message_free (sip);
      return -1;
    }
    else {
      int i;
      size_t length;

#if 0
      sdp_message_t *sdp;
      osip_body_t *oldbody;
      int pos;

      pos = 0;
      while (!osip_list_eol (&sip->bodies, pos)) {
        oldbody = (osip_body_t *) osip_list_get (&sip->bodies, pos);
        pos++;
        sdp_message_init (&sdp);
        i = sdp_message_parse (sdp, oldbody->body);
        if (i != 0) {
          fprintf (stdout, "ERROR: Bad SDP!\n");
        }
        else
          fprintf (stdout, "SUCCESS: Correct SDP!\n");
        sdp_message_free (sdp);
        sdp = NULL;
      }
#endif

      osip_message_force_update (sip);
      i = osip_message_to_str (sip, &result, &length);
      if (i == -1) {
        fprintf (stdout, "ERROR: failed while printing message!\n");
        osip_message_free (sip);
        return -1;
      }
      else {
        if (verbose)
          fwrite (result, 1, length, stdout);
        if (clone) {
          /* create a clone of message */
          /* int j = 10000; */
          int j = 1;

          if (verbose)
            fprintf (stdout, "Trying %i sequentials calls to osip_message_clone() and osip_message_free()\n", j);
          while (j != 0) {
            osip_message_t *copy;

            j--;
            i = osip_message_clone (sip, &copy);
            if (i != 0) {
              fprintf (stdout, "ERROR: failed while creating copy of message!\n");
            }
            else {
              char *tmp;
              size_t length;

              osip_message_force_update (copy);
              i = osip_message_to_str (copy, &tmp, &length);
              if (i != 0) {
                fprintf (stdout, "ERROR: failed while printing message!\n");
              }
              else {
                if (0 == strcmp (result, tmp)) {
                  if (verbose)
                    printf ("The osip_message_clone method works perfectly\n");
                }
                else
                  printf ("ERROR: The osip_message_clone method DOES NOT works\n");
                if (verbose) {
                  printf ("Here is the copy: \n");
                  fwrite (tmp, 1, length, stdout);
                  printf ("\n");
                }

                osip_free (tmp);
              }
              osip_message_free (copy);
            }
          }
          if (verbose)
            fprintf (stdout, "sequentials calls: done\n");
        }
        osip_free (result);
      }
      osip_message_free (sip);
    }
  }
  return 0;
}
Пример #10
0
        void SIPBuilder::InviteACK( osip_message_t* msg, char** rtmeg , size_t *rtlen,
                int* state)
        {//todo:小心内存泄漏
            int pos = 0;

            string request_line = "ACK sip:"+ _dev_name_ + "@" + _local_ip_str_ 
                + ":" + _local_port_str_ + " SIP/2.0" +"\r\n";
            char* via_header_c;
            int ret = ::osip_via_to_str( (osip_via_t *) osip_list_get (&msg->vias, pos), &via_header_c);
            if( ret != 0 )
            {
#ifdef DEBUG
                cout<<"via to str error"<<endl;
#endif
                *state = -1;
                return;
            }
            string via_header("Via: ");
            via_header = via_header + via_header_c + string("\r\n");

            char* from_header_c;
            ret = ::osip_from_to_str( msg->from, &from_header_c);
            if( ret != 0 )
            {
#ifdef DEBUG
                cout<<"from to str error"<<endl;
#endif
                *state = -1;
                return;
            }
            string from_header("From: ");
            from_header = from_header + from_header_c+ string("\r\n");


            char* to_header_c;
            ret = ::osip_to_to_str( msg->to, &to_header_c);
            if( ret != 0 )
            {
#ifdef DEBUG
                cout<<"to to str error"<<endl;
#endif
                *state = -1;
                return;
            }
            string to_header("To: ");
            to_header = to_header + to_header_c + string("\r\n");

            
            char* callid_header_c;
            ret = ::osip_call_id_to_str( msg->call_id, &callid_header_c);
            if( ret != 0 )
            {
#ifdef DEBUG
                cout<<"to to str error"<<endl;
#endif
                *state = -1;
                return;
            }
            string callid_header("Call-ID: ");
            callid_header = callid_header + callid_header_c + string("\r\n");

            string contact_heaer = "Contact: <sip:"+ _dev_name_ + "@" + _local_ip_str_ + ":" + _local_port_str_ +">"+"\r\n";
            string cseq_header ="CSeq: 20 ACK\r\n";
            string forwords = string("Max-Forwards: 70\r\n");
            string expires = string("Expires: 3000\r\n");
            string cflr = string("\r\n");
            string sip_msg_str = request_line + via_header + from_header + to_header + callid_header
                + contact_heaer + cseq_header + forwords + expires + cflr;

            size_t sip_len = sip_msg_str.length();
            char* sip_msg_c = (char*)malloc(sizeof(char)* sip_len);
            memcpy( sip_msg_c, sip_msg_str.c_str(), sip_len);
            *rtmeg = sip_msg_c;
            *rtlen = sip_len; 
            *state = 1;
#ifdef DEBUG
            cout<<"invite ack meg'string :\n"<<*rtmeg << endl;
#endif
            return;
        }
Пример #11
0
        void SIPBuilder::AuRegister( osip_message_t* msg, char** rtmeg, size_t* rtlen,
               std::string &via_branch_num, struct DialogInfo dlg_info,
               struct ReAuthInfo re_au)
        {
            string uas_ip = re_au.uas_ip;
            string uas_listen_port_str = re_au.uas_port_str;
            string local_dev_passwd_str = re_au.passwd;
            string remote_dev_name = re_au.remote_dev_name;
            string from_tag_num = dlg_info.from_tag_num;
            string call_id_num = dlg_info.call_id_num;
            int pos = 0;
            string realm;
            string nonce;
            if( NULL != msg)
            {
                while (!osip_list_eol (&msg->www_authenticates, pos))
                {
                    osip_www_authenticate_t* auth;
                    auth = (osip_www_authenticate_t *) osip_list_get (&msg->www_authenticates, pos);
                    realm = string(auth->realm);
                    nonce = string(auth->nonce);
                    break;
                }
            }
            string quato("\"");

            string uac_ip = _local_ip_str_;
            string uac_listen_port_str = _local_port_str_;
            string local_dev_name = _dev_name_;
            string protocol = "UDP";

            string request_line;
            stringstream request_stream;
            request_stream<<"REGISTER sip:"<< remote_dev_name<<"@"<< uas_ip<<":"<< uas_listen_port_str<<" SIP/2.0\r\n";
            request_line = request_stream.str();

            string via_header;
            string randnum = _RandomNum();
            via_branch_num = randnum;
            via_header = "Via: SIP/2.0/"+protocol+" "+uac_ip+":"+uac_listen_port_str+";rport;branch=z9hG4bK"+randnum+"\r\n";

            string to_header;
            stringstream stream_to_header;
            stream_to_header << "To: <sip:" << local_dev_name << "@" << uac_ip << ":" << uac_listen_port_str<<">\r\n";
            to_header = stream_to_header.str();

            string from_header;
            string from_tag = string("tag=") + from_tag_num;
            stringstream stream_from_header;
            stream_from_header<< "From: <sip:"<< local_dev_name <<"@"<<uac_ip << ":" << uac_listen_port_str<<">;"<< from_tag<<"\r\n";
            from_header = stream_from_header.str();

            string call_id_header = string("Call-ID: " + call_id_num + "\r\n");
            string cseq_header = string("CSeq: 2 REGISTER\r\n");

            string contact_header;
            stringstream stream_contact_header;
            stream_contact_header<<"Contact: <sip:" << local_dev_name << "@" << uac_ip << ":"<< uac_listen_port_str<<">\r\n";
            contact_header = stream_contact_header.str();

            string uri = quato +"sip:"  + remote_dev_name+ "@"+  uas_ip+":"+uas_listen_port_str + quato;
            string response = _RegisterMd5( local_dev_name, realm, local_dev_passwd_str, 
                    uri, nonce);

            string au_header;
            au_header = "Authorization: Digest username="******",realm="+ realm +",nonce=" +  nonce  
                + ",uri=" + uri + ",response="+ quato + 
                response + quato+",algorithm=MD5\r\n";
            string forwords = string("Max-Forwards: 70\r\n");
            string expires = string("Expires: 3600\r\n");
            string contentlenth = string("Content-Length: 0\r\n");
            string cflr = string("\r\n");

            string sip_msg_str = request_line + via_header + to_header + from_header
                + call_id_header + cseq_header  + contact_header +au_header +  forwords 
                + expires + contentlenth + cflr;
#ifdef DEBUG
            cout<<"check Re Au:"<<endl;
            cout<<sip_msg_str<<endl;
#endif
            size_t sip_len = sip_msg_str.length();
            char* sip_msg_c = (char*)malloc(sizeof(char)* sip_len);
            memcpy( sip_msg_c, sip_msg_str.c_str(), sip_len);
            *rtmeg = sip_msg_c;
            *rtlen = sip_len;

            return;
        }
Пример #12
0
  /* we don't have to compare
     remote_uri with from
     && local_uri with to.    ----> we have both tag recognized, it's enough..
   */
  if (0 == strcmp (tag_param_remote->gvalue, dlg->remote_tag))
    return 0;

  return -1;
}

int
osip_dialog_init_as_uac (osip_dialog_t ** dialog, osip_message_t * response)
{
  int i;
  int pos;
  osip_generic_param_t *tag;

  *dialog = NULL;

  (*dialog) = (osip_dialog_t *) osip_malloc (sizeof (osip_dialog_t));
  if (*dialog == NULL)
    return -1;

  memset (*dialog, 0, sizeof (osip_dialog_t));

  (*dialog)->your_instance = NULL;

  (*dialog)->type = CALLER;
  if (MSG_IS_STATUS_2XX (response))
    (*dialog)->state = DIALOG_CONFIRMED;
  else                          /* 1XX */
    (*dialog)->state = DIALOG_EARLY;

  i = osip_call_id_to_str (response->call_id, &((*dialog)->call_id));
  if (i != 0)
    goto diau_error_0;

  i = osip_from_get_tag (response->from, &tag);
  if (i != 0)
    goto diau_error_1;
  (*dialog)->local_tag = osip_strdup (tag->gvalue);

  i = osip_to_get_tag (response->to, &tag);
  if (i != 0)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_WARNING, NULL,
                   "Remote UA is not compliant: missing a tag in response!\n"));
      (*dialog)->remote_tag = NULL;
  } else
    (*dialog)->remote_tag = osip_strdup (tag->gvalue);

  osip_list_init (&(*dialog)->route_set);

  pos = 0;
  while (!osip_list_eol (&response->record_routes, pos))
    {
      osip_record_route_t *rr;
      osip_record_route_t *rr2;

      rr = (osip_record_route_t *) osip_list_get (&response->record_routes, pos);
      i = osip_record_route_clone (rr, &rr2);
      if (i != 0)
        goto diau_error_2;
      osip_list_add (&(*dialog)->route_set, rr2, 0);
      pos++;
    }

  (*dialog)->local_cseq = osip_atoi (response->cseq->number);
  (*dialog)->remote_cseq = -1;

  i = osip_to_clone (response->to, &((*dialog)->remote_uri));
  if (i != 0)
    goto diau_error_3;

  i = osip_from_clone (response->from, &((*dialog)->local_uri));
  if (i != 0)
    goto diau_error_4;

  {
    osip_contact_t *contact;

    if (!osip_list_eol (&response->contacts, 0))
      {
        contact = osip_list_get (&response->contacts, 0);
        i = osip_contact_clone (contact, &((*dialog)->remote_contact_uri));
        if (i != 0)
          goto diau_error_5;
    } else
      {
        (*dialog)->remote_contact_uri = NULL;
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_WARNING, NULL,
                     "Remote UA is not compliant: missing a contact in response!\n"));
      }
  }
  (*dialog)->secure = -1;       /* non secure */

  return 0;

diau_error_5:
  osip_from_free ((*dialog)->local_uri);
diau_error_4:
  osip_from_free ((*dialog)->remote_uri);
diau_error_3:
diau_error_2:
  osip_list_special_free (&(*dialog)->route_set,
                          (void *(*)(void *)) &osip_record_route_free);
  osip_free ((*dialog)->remote_tag);
  osip_free ((*dialog)->local_tag);
diau_error_1:
  osip_free ((*dialog)->call_id);
diau_error_0:
  OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
               "Could not establish dialog!\n"));
  osip_free (*dialog);
  *dialog = NULL;
  return -1;
}

#if 1                           /* SIPIT13 */
int
osip_dialog_init_as_uac_with_remote_request (osip_dialog_t ** dialog,
                                             osip_message_t * next_request,
                                             int local_cseq)
{
  int i;
  osip_generic_param_t *tag;

  *dialog = NULL;

  (*dialog) = (osip_dialog_t *) osip_malloc (sizeof (osip_dialog_t));
  if (*dialog == NULL)
    return -1;

  memset (*dialog, 0, sizeof (osip_dialog_t));
  (*dialog)->your_instance = NULL;

  (*dialog)->type = CALLER;
#if 0
  (*dialog)->state = DIALOG_CONFIRMED;
#endif
  (*dialog)->state = DIALOG_EARLY;

  i = osip_call_id_to_str (next_request->call_id, &((*dialog)->call_id));
  if (i != 0)
    goto diau_error_0;

  i = osip_from_get_tag (next_request->to, &tag);
  if (i != 0)
    goto diau_error_1;
  (*dialog)->local_tag = osip_strdup (tag->gvalue);

  i = osip_to_get_tag (next_request->from, &tag);
  if (i != 0)
    {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_WARNING, NULL,
                   "Remote UA is not compliant: missing a tag in next request!\n"));
      (*dialog)->remote_tag = NULL;
  } else
    (*dialog)->remote_tag = osip_strdup (tag->gvalue);

  osip_list_init (&(*dialog)->route_set);

  (*dialog)->local_cseq = local_cseq;   /* -1 osip_atoi (xxx->cseq->number); */
  (*dialog)->remote_cseq = osip_atoi (next_request->cseq->number);

  i = osip_to_clone (next_request->from, &((*dialog)->remote_uri));
  if (i != 0)
    goto diau_error_3;

  i = osip_from_clone (next_request->to, &((*dialog)->local_uri));
  if (i != 0)
    goto diau_error_4;

  {
    osip_contact_t *contact;

    if (!osip_list_eol (&next_request->contacts, 0))
      {
        contact = osip_list_get (&next_request->contacts, 0);
        i = osip_contact_clone (contact, &((*dialog)->remote_contact_uri));
        if (i != 0)
          goto diau_error_5;
    } else
      {
        (*dialog)->remote_contact_uri = NULL;
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_WARNING, NULL,
                     "Remote UA is not compliant? missing a contact in response!\n"));
      }
  }

  (*dialog)->secure = -1;       /* non secure */

  return 0;

diau_error_5:
  osip_from_free ((*dialog)->local_uri);
diau_error_4:
  osip_from_free ((*dialog)->remote_uri);
diau_error_3:
  osip_free ((*dialog)->remote_tag);
  osip_free ((*dialog)->local_tag);
diau_error_1:
  osip_free ((*dialog)->call_id);
diau_error_0:
  OSIP_TRACE (osip_trace
              (__FILE__, __LINE__, OSIP_ERROR, NULL,
               "Could not establish dialog!\n"));
  osip_free (*dialog);
  *dialog = NULL;
  return -1;
}
Пример #13
0
int
_eXosip_build_response_default (struct eXosip_t *excontext, osip_message_t ** dest, osip_dialog_t * dialog, int status, osip_message_t * request)
{
  osip_generic_param_t *tag;
  osip_message_t *response;
  int pos;
  int i;

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

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

  response->sip_version = (char *) osip_malloc (8 * sizeof (char));
  if (response->sip_version == NULL) {
    osip_message_free (response);
    return OSIP_NOMEM;
  }
  sprintf (response->sip_version, "SIP/2.0");
  osip_message_set_status_code (response, status);

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

  if (response->reason_phrase == NULL) {
    osip_message_free (response);
    return OSIP_NOMEM;
  }

  i = osip_to_clone (request->to, &(response->to));
  if (i != 0) {
    osip_message_free (response);
    return i;
  }

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

  i = osip_from_clone (request->from, &(response->from));
  if (i != 0) {
    osip_message_free (response);
    return i;
  }

  pos = 0;
  while (!osip_list_eol (&request->vias, pos)) {
    osip_via_t *via;
    osip_via_t *via2;

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

  i = osip_call_id_clone (request->call_id, &(response->call_id));
  if (i != 0) {
    osip_message_free (response);
    return i;
  }
  i = osip_cseq_clone (request->cseq, &(response->cseq));
  if (i != 0) {
    osip_message_free (response);
    return i;
  }
#ifndef MINISIZE
  if (MSG_IS_SUBSCRIBE (request)) {
    osip_header_t *exp;
    osip_header_t *evt_hdr;

    osip_message_header_get_byname (request, "event", 0, &evt_hdr);
    if (evt_hdr != NULL && evt_hdr->hvalue != NULL)
      osip_message_set_header (response, "Event", evt_hdr->hvalue);
    else
      osip_message_set_header (response, "Event", "presence");
    i = osip_message_get_expires (request, 0, &exp);
    if (exp == NULL) {
      osip_header_t *cp;

      i = osip_header_clone (exp, &cp);
      if (cp != NULL)
        osip_list_add (&response->headers, cp, 0);
    }
  }
#endif

  osip_message_set_user_agent (response, excontext->user_agent);

  *dest = response;
  return OSIP_SUCCESS;
}
Пример #14
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;
}
Пример #15
0
osip_transaction_t *
_eXosip_find_previous_invite (eXosip_call_t * jc, eXosip_dialog_t * jd, osip_transaction_t * last_invite)
{
  osip_transaction_t *inc_tr;
  osip_transaction_t *out_tr;
  int pos;

  inc_tr = NULL;
  pos = 0;
  if (jd != NULL) {
    while (!osip_list_eol (jd->d_inc_trs, pos)) {
      inc_tr = osip_list_get (jd->d_inc_trs, pos);
      if (inc_tr == last_invite) {
        /* we don't want the current one */
        inc_tr = NULL;
      }
      else if (0 == strcmp (inc_tr->cseq->method, "INVITE"))
        break;
      else
        inc_tr = NULL;
      pos++;
    }
  }
  else
    inc_tr = NULL;

  if (inc_tr == NULL)
    inc_tr = jc->c_inc_tr;      /* can be NULL */
  if (inc_tr == last_invite) {
    /* we don't want the current one */
    inc_tr = NULL;
  }

  out_tr = NULL;
  pos = 0;

  if (jd != NULL) {
    while (!osip_list_eol (jd->d_out_trs, pos)) {
      out_tr = osip_list_get (jd->d_out_trs, pos);
      if (out_tr == last_invite) {
        /* we don't want the current one */
        out_tr = NULL;
      }
      else if (0 == strcmp (out_tr->cseq->method, "INVITE"))
        break;
      else
        out_tr = NULL;
      pos++;
    }
  }

  if (out_tr == NULL)
    out_tr = jc->c_out_tr;      /* can be NULL */

  if (out_tr == last_invite) {
    /* we don't want the current one */
    out_tr = NULL;
  }

  if (inc_tr == NULL)
    return out_tr;
  if (out_tr == NULL)
    return inc_tr;

  if (inc_tr->birth_time > out_tr->birth_time)
    return inc_tr;
  return out_tr;
}
Пример #16
0
int eXosip_reinvite_with_authentication (struct eXosip_call_t *jc)
{
    struct eXosip_call_t *jcc;
#ifdef SM

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

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

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

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

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

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

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

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

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

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

    eXosip_update(); /* fixed? */
    __eXosip_wakeup();
	return 0;
}
Пример #17
0
int
osip_uri_test_accessor_api (osip_uri_t * url)
{
  if (url->scheme != NULL)
    fprintf (stdout, "%s:", url->scheme);
  if (url->string != NULL)
    {
      fprintf (stdout, "|%s", url->string);
      fprintf (stdout, "\n");
      return 0;
    }
  if (url->username != NULL)
    fprintf (stdout, "%s|", url->username);

  if ((url->password != NULL) && (url->username != NULL))
    fprintf (stdout, ":%s|", url->password);
  if (url->username != NULL)
    fprintf (stdout, "@|");
  /*   if (url->host!=NULL)  mandatory */
  if (strchr (url->host, ':') != NULL)
    fprintf (stdout, "[%s]|", url->host);
  else
    fprintf (stdout, "%s|", url->host);
  if (url->port != NULL)
    fprintf (stdout, ":%s|", url->port);

  fprintf (stdout, "\nuri-params\n");

  {
    int pos = 0;
    osip_uri_param_t *u_param;

    while (!osip_list_eol (&url->url_params, pos))
      {
        u_param = (osip_uri_param_t *) osip_list_get (&url->url_params, pos);
        if (u_param->gvalue != NULL)
          fprintf (stdout, ";%s|=|%s|", u_param->gname, u_param->gvalue);
        else
          fprintf (stdout, ";%s|", u_param->gname);
        pos++;
      }
  }

  fprintf (stdout, "\nheaders\n");

  {
    int pos = 0;
    osip_uri_header_t *u_header;

    while (!osip_list_eol (&url->url_headers, pos))
      {
        u_header = (osip_uri_header_t *) osip_list_get (&url->url_headers, pos);
        if (pos == 0)
          fprintf (stdout, "?%s|=|%s|", u_header->gname, u_header->gvalue);
        else
          fprintf (stdout, "&%s|=|%s|", u_header->gname, u_header->gvalue);
        pos++;
      }
  }
  fprintf (stdout, "\n");
  return 0;
}
Пример #18
0
static int
sdp_confirm_media (osip_negotiation_t * config,
		   osip_negotiation_ctx_t * context, sdp_message_t * remote,
		   sdp_message_t ** dest)
{
  char *payload;
  char *tmp, *tmp2, *tmp3, *tmp4;
  int ret;
  int i;
  int k;
  int audio_qty = 0;		/* accepted audio line: do not accept more than one */
  int video_qty = 0;

  i = 0;
  while (!sdp_message_endof_media (remote, i))
    {
      tmp = sdp_message_m_media_get (remote, i);
      tmp2 = sdp_message_m_port_get (remote, i);
      tmp3 = sdp_message_m_number_of_port_get (remote, i);
      tmp4 = sdp_message_m_proto_get (remote, i);

      if (tmp == NULL)
	return -1;
      sdp_message_m_media_add (*dest, osip_strdup (tmp), osip_strdup ("0"),
			       NULL, osip_strdup (tmp4));
      k = 0;
      if (0 == strncmp (tmp, "audio", 5))
	{
	  do
	    {
	      payload = sdp_message_m_payload_get (remote, i, k);
	      if (payload != NULL)
		{
		  __payload_t *my_payload =
		    osip_negotiation_find_audio_payload (config, payload);

		  if (my_payload != NULL)	/* payload is supported */
		    {
		      ret = -1;	/* somtimes, codec can be refused even if supported */
		      if (config->fcn_accept_audio_codec != NULL)
			ret = config->fcn_accept_audio_codec (context, tmp2,
							      tmp3, audio_qty,
							      payload);
		      if (0 == ret)
			{
			  sdp_message_m_payload_add (*dest, i,
						     osip_strdup (payload));
			  if (my_payload->a_rtpmap != NULL)
			    sdp_message_a_attribute_add (*dest, i,
							 osip_strdup
							 ("rtpmap"),
							 osip_strdup
							 (my_payload->
							  a_rtpmap));
			  if (my_payload->c_nettype != NULL)
			    {
			      sdp_media_t *med =
				osip_list_get ((*dest)->m_medias, i);

			      if (osip_list_eol (med->c_connections, 0))
				sdp_message_c_connection_add (*dest, i,
							      osip_strdup
							      (my_payload->
							       c_nettype),
							      osip_strdup
							      (my_payload->
							       c_addrtype),
							      osip_strdup
							      (my_payload->
							       c_addr),
							      osip_strdup
							      (my_payload->
							       c_addr_multicast_ttl),
							      osip_strdup
							      (my_payload->
							       c_addr_multicast_int));
			    }
			}
		    }
		}
	      k++;
	    }
	  while (payload != NULL);
	  if (NULL != sdp_message_m_payload_get (*dest, i, 0))
	    audio_qty = 1;
	}
      else if (0 == strncmp (tmp, "video", 5))
	{
	  do
	    {
	      payload = sdp_message_m_payload_get (remote, i, k);
	      if (payload != NULL)
		{
		  __payload_t *my_payload =
		    osip_negotiation_find_video_payload (config, payload);

		  if (my_payload != NULL)	/* payload is supported */
		    {
		      ret = -1;
		      if (config->fcn_accept_video_codec != NULL)
			ret =
			  config->fcn_accept_video_codec (context, tmp2, tmp3,
							  video_qty, payload);
		      if (0 == ret)
			{
			  sdp_message_m_payload_add (*dest, i,
						     osip_strdup (payload));
			  /* TODO  set the attribute list (rtpmap..) */
			  if (my_payload->a_rtpmap != NULL)
			    sdp_message_a_attribute_add (*dest, i,
							 osip_strdup
							 ("rtpmap"),
							 osip_strdup
							 (my_payload->
							  a_rtpmap));
			  if (my_payload->c_nettype != NULL)
			    {
			      sdp_media_t *med =
				osip_list_get ((*dest)->m_medias, i);

			      if (osip_list_eol (med->c_connections, 0))
				sdp_message_c_connection_add (*dest, i,
							      osip_strdup
							      (my_payload->
							       c_nettype),
							      osip_strdup
							      (my_payload->
							       c_addrtype),
							      osip_strdup
							      (my_payload->
							       c_addr),
							      osip_strdup
							      (my_payload->
							       c_addr_multicast_ttl),
							      osip_strdup
							      (my_payload->
							       c_addr_multicast_int));
			    }
			}
		    }
		}
	      k++;
	    }
	  while (payload != NULL);
	  if (NULL != sdp_message_m_payload_get (*dest, i, 0))
	    video_qty = 1;
	}
      else
	{
	  do
	    {
	      payload = sdp_message_m_payload_get (remote, i, k);
	      if (payload != NULL)
		{
		  __payload_t *my_payload =
		    osip_negotiation_find_other_payload (config, payload);

		  if (my_payload != NULL)	/* payload is supported */
		    {
		      ret = -1;
		      if (config->fcn_accept_other_codec != NULL)
			ret =
			  config->fcn_accept_other_codec (context, tmp, tmp2,
							  tmp3, payload);
		      if (0 == ret)
			{
			  sdp_message_m_payload_add (*dest, i,
						     osip_strdup (payload));
			  /* rtpmap has no meaning here! */
			  if (my_payload->c_nettype != NULL)
			    {
			      sdp_media_t *med =
				osip_list_get ((*dest)->m_medias, i);

			      if (osip_list_eol (med->c_connections, 0))
				sdp_message_c_connection_add (*dest, i,
							      osip_strdup
							      (my_payload->
							       c_nettype),
							      osip_strdup
							      (my_payload->
							       c_addrtype),
							      osip_strdup
							      (my_payload->
							       c_addr),
							      osip_strdup
							      (my_payload->
							       c_addr_multicast_ttl),
							      osip_strdup
							      (my_payload->
							       c_addr_multicast_int));
			    }
			}
		    }
		}
	      k++;
	    }
	  while (payload != NULL);
	}
      i++;
    }
  return 0;
}
Пример #19
0
/* returns null on error. */
int
osip_accept_to_str (const osip_accept_t * accept, char **dest)
{
  char *buf;
  char *tmp;
  size_t len;

  *dest = NULL;
  if (accept == NULL)
    return -1;

  if ((accept->type == NULL) && (accept->subtype == NULL))
    {
      /* Empty header ! */
      buf = (char *) osip_malloc (2);
      buf[0] = ' ';
      buf[1] = '\0';
      *dest = buf;
      return 0;
    }

  /* try to guess a long enough length */
  len = strlen (accept->type) + strlen (accept->subtype) + 4    /* for '/', ' ', ';' and '\0' */
    + 10 * osip_list_size (accept->gen_params);

  buf = (char *) osip_malloc (len);
  tmp = buf;

  sprintf (tmp, "%s/%s", accept->type, accept->subtype);

  tmp = tmp + strlen (tmp);
  {
    int pos = 0;
    osip_generic_param_t *u_param;

#if 0
    if (!osip_list_eol (accept->gen_params, pos))
      {                         /* needed for cannonical form! (authentication issue of rfc2543) */
        sprintf (tmp, " ");
        tmp++;
      }
#endif
    while (!osip_list_eol (accept->gen_params, pos))
      {
        size_t tmp_len;

        u_param = (osip_generic_param_t *) osip_list_get (accept->gen_params, pos);
        if (u_param->gvalue == NULL)
          {
            osip_free (buf);
            return -1;
          }
        tmp_len = strlen (buf) + 4 + strlen (u_param->gname)
          + strlen (u_param->gvalue) + 1;
        if (len < tmp_len)
          {
            buf = osip_realloc (buf, tmp_len);
            len = tmp_len;
            tmp = buf + strlen (buf);
          }
        sprintf (tmp, "; %s=%s", u_param->gname, u_param->gvalue);
        tmp = tmp + strlen (tmp);
        pos++;
      }
  }
  *dest = buf;
  return 0;
}
Пример #20
0
int
osip_negotiation_ctx_execute_negotiation (osip_negotiation_t * config,
					  osip_negotiation_ctx_t * context)
{
  int m_lines_that_match = 0;
  sdp_message_t *remote;
  sdp_message_t *local;
  int i;

  if (context == NULL)
    return -1;
  remote = context->remote;
  if (remote == NULL)
    return -1;

  i = sdp_message_init (&local);
  if (i != 0)
    return -1;

  if (0 != strncmp (remote->v_version, "0", 1))
    {
      sdp_message_free (local);
      /*      sdp_context->fcn_wrong_version(context); */
      return 406;		/* Not Acceptable */
    }

  i = sdp_partial_clone (config, context, remote, &local);
  if (i != 0)
    {
      sdp_message_free (local);
      return -1;
    }
  i = sdp_confirm_media (config, context, remote, &local);
  if (i != 0)
    {
      sdp_message_free (local);
      return i;
    }

  i = 0;
  while (!sdp_message_endof_media (local, i))
    {
      /* this is to refuse each line with no codec that matches! */
      if (NULL == sdp_message_m_payload_get (local, i, 0))
	{
	  sdp_media_t *med = osip_list_get ((local)->m_medias, i);
	  char *str = sdp_message_m_payload_get (remote, i, 0);

	  sdp_message_m_payload_add (local, i, osip_strdup (str));
	  osip_free (med->m_port);
	  med->m_port = osip_strdup ("0");	/* refuse this line */
	}
      else
	{			/* number of "m" lines that match */
	  sdp_media_t *med = osip_list_get (local->m_medias, i);

	  m_lines_that_match++;
	  osip_free (med->m_port);
	  /* AMD: use the correct fcn_get_xxx_port method: */
	  if (0 == strcmp (med->m_media, "audio"))
	    {
	      if (config->fcn_get_audio_port != NULL)
		med->m_port = config->fcn_get_audio_port (context, i);
	      else
		med->m_port = osip_strdup ("0");	/* should never happen */
	    }
	  else if (0 == strcmp (med->m_media, "video"))
	    {
	      if (config->fcn_get_video_port != NULL)
		med->m_port = config->fcn_get_video_port (context, i);
	      else
		med->m_port = osip_strdup ("0");	/* should never happen */
	    }
	  else
	    {
	      if (config->fcn_get_other_port != NULL)
		med->m_port = config->fcn_get_other_port (context, i);
	      else
		med->m_port = osip_strdup ("0");	/* should never happen */
	    }
	}
      i++;
    }
  if (m_lines_that_match > 0)
    {
      context->local = local;
      return 200;
    }
  else
    {
      sdp_message_free (local);
      return 415;
    }

}
Пример #21
0
osip_message_t *ict_create_ack(osip_transaction_t * ict, osip_message_t * response)
{
	int i;
	osip_message_t *ack;

	i = osip_message_init(&ack);
	if (i != 0)
		return NULL;

	/* Section 17.1.1.3: Construction of the ACK request: */
	i = osip_from_clone(response->from, &(ack->from));
	if (i != 0) {
		osip_message_free(ack);
		return NULL;
	}
	i = osip_to_clone(response->to, &(ack->to));	/* include the tag! */
	if (i != 0) {
		osip_message_free(ack);
		return NULL;
	}
	i = osip_call_id_clone(response->call_id, &(ack->call_id));
	if (i != 0) {
		osip_message_free(ack);
		return NULL;
	}
	i = osip_cseq_clone(response->cseq, &(ack->cseq));
	if (i != 0) {
		osip_message_free(ack);
		return NULL;
	}
	osip_free(ack->cseq->method);
	ack->cseq->method = osip_strdup("ACK");
	if (ack->cseq->method == NULL) {
		osip_message_free(ack);
		return NULL;
	}

	ack->sip_method = (char *) osip_malloc(5);
	if (ack->sip_method == NULL) {
		osip_message_free(ack);
		return NULL;
	}
	sprintf(ack->sip_method, "ACK");
	ack->sip_version = osip_strdup(ict->orig_request->sip_version);
	if (ack->sip_version == NULL) {
		osip_message_free(ack);
		return NULL;
	}

	ack->status_code = 0;
	ack->reason_phrase = NULL;

	/* MUST copy REQUEST-URI from Contact header! */
	i = osip_uri_clone(ict->orig_request->req_uri, &(ack->req_uri));
	if (i != 0) {
		osip_message_free(ack);
		return NULL;
	}

	/* ACK MUST contain only the TOP Via field from original request */
	{
		osip_via_t *via;
		osip_via_t *orig_via;

		osip_message_get_via(ict->orig_request, 0, &orig_via);
		if (orig_via == NULL) {
			osip_message_free(ack);
			return NULL;
		}
		i = osip_via_clone(orig_via, &via);
		if (i != 0) {
			osip_message_free(ack);
			return NULL;
		}
		osip_list_add(&ack->vias, via, -1);
	}

	/* ack MUST contains the ROUTE headers field from the original request */
	/* IS IT TRUE??? */
	/* if the answers contains a set of route (or record route), then it */
	/* should be used instead?? ......May be not..... */
	{
		int pos = 0;
		osip_route_t *route;
		osip_route_t *orig_route;

		while (!osip_list_eol(&ict->orig_request->routes, pos)) {
			orig_route =
				(osip_route_t *) osip_list_get(&ict->orig_request->routes, pos);
			i = osip_route_clone(orig_route, &route);
			if (i != 0) {
				osip_message_free(ack);
				return NULL;
			}
			osip_list_add(&ack->routes, route, -1);
			pos++;
		}
	}

	/* may be we could add some other headers: */
	/* For example "Max-Forward" */

	return ack;
}
Пример #22
0
int
osip_negotiation_sdp_build_offer (osip_negotiation_t * config,
				  osip_negotiation_ctx_t * con,
				  sdp_message_t ** sdp, char *audio_port,
				  char *video_port)
{
  int i;
  int media_line = 0;

  i = sdp_message_init (sdp);
  if (i != 0)
    return -1;

  sdp_message_v_version_set (*sdp, osip_strdup ("0"));

  /* those fields MUST be set */
  sdp_message_o_origin_set (*sdp,
			    osip_strdup (config->o_username),
			    osip_strdup (config->o_session_id),
			    osip_strdup (config->o_session_version),
			    osip_strdup (config->o_nettype),
			    osip_strdup (config->o_addrtype),
			    osip_strdup (config->o_addr));
  sdp_message_s_name_set (*sdp, osip_strdup ("A call"));
  if (config->fcn_set_info != NULL)
    config->fcn_set_info (con, *sdp);
  if (config->fcn_set_uri != NULL)
    config->fcn_set_uri (con, *sdp);
  if (config->fcn_set_emails != NULL)
    config->fcn_set_emails (con, *sdp);
  if (config->fcn_set_phones != NULL)
    config->fcn_set_phones (con, *sdp);
  if (config->c_nettype != NULL)
    sdp_message_c_connection_add (*sdp, -1,
				  osip_strdup (config->c_nettype),
				  osip_strdup (config->c_addrtype),
				  osip_strdup (config->c_addr),
				  osip_strdup (config->c_addr_multicast_ttl),
				  osip_strdup (config->c_addr_multicast_int));

  {				/* offer-answer draft says we must copy the "t=" line */
    /*BEGIN 3082101267 00201037 20130823 modified*/
    int now = osip_time (NULL);
    /*END 3082101267 00201037 20130823 modified*/

    char *tmp = osip_malloc (15);
    char *tmp2 = osip_malloc (15);

    sprintf (tmp, "%i", now);
    sprintf (tmp2, "%i", now + 3600);

    i = sdp_message_t_time_descr_add (*sdp, tmp, tmp2);
    if (i != 0)
      return -1;
  }
  if (config->fcn_set_attributes != NULL)
    config->fcn_set_attributes (con, *sdp, -1);


  /* add all audio codec */
  if (!osip_list_eol (config->audio_codec, 0))
    {
      int pos = 0;
      __payload_t *my =
	(__payload_t *) osip_list_get (config->audio_codec, pos);

      /* all media MUST have the same PROTO, PORT. */
      sdp_message_m_media_add (*sdp, osip_strdup ("audio"),
			       osip_strdup (audio_port),
			       osip_strdup (my->number_of_port),
			       osip_strdup (my->proto));

      while (!osip_list_eol (config->audio_codec, pos))
	{
	  my = (__payload_t *) osip_list_get (config->audio_codec, pos);
	  sdp_message_m_payload_add (*sdp, media_line,
				     osip_strdup (my->payload));
	  if (my->a_rtpmap != NULL)
	    sdp_message_a_attribute_add (*sdp, media_line,
					 osip_strdup ("rtpmap"),
					 osip_strdup (my->a_rtpmap));
	  pos++;
	}
      media_line++;
    }

  /* add all video codec */
  if (!osip_list_eol (config->video_codec, 0))
    {
      int pos = 0;
      __payload_t *my =
	(__payload_t *) osip_list_get (config->video_codec, pos);

      /* all media MUST have the same PROTO, PORT. */
      sdp_message_m_media_add (*sdp, osip_strdup ("video"),
			       osip_strdup (video_port),
			       osip_strdup (my->number_of_port),
			       osip_strdup (my->proto));

      while (!osip_list_eol (config->video_codec, pos))
	{
	  my = (__payload_t *) osip_list_get (config->video_codec, pos);
	  sdp_message_m_payload_add (*sdp, media_line,
				     osip_strdup (my->payload));
	  if (my->a_rtpmap != NULL)
	    sdp_message_a_attribute_add (*sdp, media_line,
					 osip_strdup ("rtpmap"),
					 osip_strdup (my->a_rtpmap));
	  pos++;
	}
      media_line++;
    }
  return 0;
}
Пример #23
0
int
osip_from_compare (osip_from_t * from1, osip_from_t * from2)
{
  char *tag1;
  char *tag2;

  if (from1 == NULL || from2 == NULL)
    return -1;
  if (from1->url == NULL || from2->url == NULL)
    return -1;

  /* we could have a sip or sips url, but if string!=NULL,
     host part will be NULL. */
  if (from1->url->host == NULL && from2->url->host == NULL)
    {
      if (from1->url->string == NULL || from2->url->string == NULL)
        return -1;
      if (0 == strcmp (from1->url->string, from2->url->string))
        return 0;
    }
  if (from1->url->host == NULL || from2->url->host == NULL)
    return -1;

  /* compare url including tag */
  if (0 != strcmp (from1->url->host, from2->url->host))
    return -1;
  if (from1->url->username != NULL && from2->url->username != NULL)
    if (0 != strcmp (from1->url->username, from2->url->username))
      return -1;

  tag1 = NULL;
  tag2 = NULL;
  {
    int pos = 0;
    osip_generic_param_t *u_param;

    while (!osip_list_eol (&from1->gen_params, pos))
      {
        u_param = (osip_generic_param_t *) osip_list_get (&from1->gen_params, pos);
        if (0 == strncmp (u_param->gname, "tag", 3))
          {
            tag1 = u_param->gvalue;
            break;
          }
        pos++;
      }
  }
  {
    int pos = 0;
    osip_generic_param_t *u_param;

    while (!osip_list_eol (&from2->gen_params, pos))
      {
        u_param = (osip_generic_param_t *) osip_list_get (&from2->gen_params, pos);
        if (0 == strncmp (u_param->gname, "tag", 3))
          {
            tag2 = u_param->gvalue;
            break;
          }
        pos++;
      }
  }

  /* sounds like a BUG!
     if tag2 exists and tag1 does not, then it will
     return 0;
     in the first request, (INVITE) the To field does not
     contain any tag. The response contains one! and the
     response must match the request....
   */
  /* so we test the tags only when both exist! */
  if (tag1 != NULL && tag2 != NULL)
    if (0 != strcmp (tag1, tag2))
      return -1;

  /* We could return a special case, when */
  /* only one tag exists?? */

  return 0;                     /* return code changed to 0 from release 0.6.1 */
}
Пример #24
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;
}
Пример #25
0
int GB_handle_RCV_STATUS_4XX(GB_CONNECT_STATE *gb_cons, osip_event_t * osip_event)
{
	if(gb_cons == NULL || osip_event == NULL || osip_event->sip == NULL)
	{
		return -1;
	}
	
	switch(osip_event->sip->status_code)
	{
		case 401: // 未授权
		{
			if(gb_cons->cur_state == GB_STATE_REGISTER)  
			{
				osip_www_authenticate_t * wwwa;

				if(gb_cons->wwwa != NULL)
				{
					TRACE(SCI_TRACE_NORMAL,MOD_GB,"%s  line=%d  Unauthorized, Please Check Carefully!\n",__FUNCTION__,__LINE__);
				}
				
				wwwa = osip_list_get (&osip_event->sip->www_authenticates, 0);
				if (wwwa != NULL)
				{
					osip_www_authenticate_free(gb_cons->wwwa);
					osip_www_authenticate_clone(wwwa, &gb_cons->wwwa);
					GB_sipd_register_auth(gb_cons, 0); //  带认证的注册请求
					gb_cons->last_sendtime = get_cur_time()/1000;
				}
			}
			else if(gb_cons->cur_state == GB_STATE_RUNNING && gb_cons->bUnRegister == 1)  
			{
				osip_www_authenticate_t * wwwa;

				wwwa = osip_list_get (&osip_event->sip->www_authenticates, 0);
				if (wwwa != NULL)
				{
					osip_www_authenticate_free(gb_cons->wwwa);
					osip_www_authenticate_clone(wwwa, &gb_cons->wwwa);
					GB_sipd_register_auth(gb_cons, 1); //  带认证的注销请求
					gb_cons->last_sendtime = get_cur_time()/1000;
				}
			}
		}
		break;
		case 403: // 禁止
		{
			// 重新认证
			if(gb_cons->cur_state == GB_STATE_RUNNING && gb_cons->bUnRegister == 0)
			{
				close(gb_cons->connfd);
				GB_ResetConState(gb_cons);

				GB_Refresh_GBCfg();
				GB_Set_gGBConnStatus(0);

				TRACE(SCI_TRACE_NORMAL,MOD_GB,"%s  line=%d  Get 403 err, Register again\n",__FUNCTION__,__LINE__);
			}
			
		}
		break;

		default:
			TRACE(SCI_TRACE_NORMAL,MOD_GB,"Can't handle sip->status_code=%d  message\n",osip_event->sip->status_code);
			break;
	}
	
	return 0;
}
Пример #26
0
int
_eXosip_subscribe_send_request_with_credential (struct eXosip_t *excontext, eXosip_subscribe_t * js, eXosip_dialog_t * jd, osip_transaction_t * out_tr)
{
  osip_transaction_t *tr = NULL;
  osip_message_t *msg = NULL;
  osip_event_t *sipevent;

  int cseq;
  osip_via_t *via;
  int i;

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

  if (out_tr == NULL) {
    out_tr = _eXosip_find_last_out_subscribe (js, jd);
  }

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

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

  {
    osip_generic_param_t *tag = NULL;

    osip_to_get_tag (msg->to, &tag);
    if (NULL == tag && jd != NULL && jd->d_dialog != NULL && jd->d_dialog->remote_tag != NULL) {
      osip_to_set_tag (msg->to, osip_strdup (jd->d_dialog->remote_tag));
    }
  }

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

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

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

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

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

  if (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407) {
    _eXosip_add_authentication_information (excontext, msg, out_tr->last_response);
  }
  else
    _eXosip_add_authentication_information (excontext, msg, NULL);


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

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


  osip_message_force_update (msg);

  i = _eXosip_transaction_init (excontext, &tr, NICT, excontext->j_osip, msg);

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

  if (out_tr == js->s_out_tr) {
    /* replace with the new tr */
    osip_list_add (&excontext->j_transactions, js->s_out_tr, 0);
    js->s_out_tr = tr;
  }
  else {
    /* add the new tr for the current dialog */
    osip_list_add (jd->d_out_trs, tr, 0);
  }

  sipevent = osip_new_outgoing_sipmessage (msg);

  osip_transaction_set_reserved5 (tr, js);
  osip_transaction_set_reserved3 (tr, jd);

  osip_transaction_add_event (tr, sipevent);

  _eXosip_update (excontext);   /* fixed? */
  _eXosip_wakeup (excontext);
  return OSIP_SUCCESS;
}
Пример #27
0
int
_eXosip_insubscription_send_request_with_credential (eXosip_notify_t * jn,
        eXosip_dialog_t * jd,
        osip_transaction_t * out_tr)
{
    osip_transaction_t *tr = NULL;
    osip_message_t *msg = NULL;
    osip_event_t *sipevent;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    sipevent = osip_new_outgoing_sipmessage (msg);

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

    eXosip_update ();             /* fixed? */
    __eXosip_wakeup ();
    return 0;
}
Пример #28
0
int
osip_dialog_init_as_uas (osip_dialog_t ** dialog, osip_message_t * invite, osip_message_t * response)
{
    int i;
    int pos;
    osip_generic_param_t *tag;

    (*dialog) = (osip_dialog_t *) osip_malloc (sizeof (osip_dialog_t));
    if (*dialog == NULL)
        return -1;

    (*dialog)->type = CALLEE;
    if (MSG_IS_STATUS_2XX (response))
        (*dialog)->state = DIALOG_CONFIRMED;
    else				/* 1XX */
        (*dialog)->state = DIALOG_EARLY;

    i = osip_call_id_to_str (response->call_id, &((*dialog)->call_id));
    if (i != 0)
        goto diau_error_0;

    i = osip_to_get_tag (response->to, &tag);
    if (i != 0)
        goto diau_error_1;
    (*dialog)->local_tag = osip_strdup (tag->gvalue);

    i = osip_from_get_tag (response->from, &tag);
    if (i != 0)
    {
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_WARNING, NULL,
                     "Remote UA is not compliant: missing a tag in response!\n"));
        (*dialog)->remote_tag = NULL;
    }
    else
        (*dialog)->remote_tag = osip_strdup (tag->gvalue);

    (*dialog)->route_set = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
    osip_list_init ((*dialog)->route_set);

    pos = 0;
    while (!osip_list_eol (response->record_routes, pos))
    {
        osip_record_route_t *rr;
        osip_record_route_t *rr2;

        rr = (osip_record_route_t *) osip_list_get (response->record_routes, pos);
        i = osip_record_route_clone (rr, &rr2);
        if (i != 0)
            goto diau_error_2;
        osip_list_add ((*dialog)->route_set, rr2, -1);
        pos++;
    }

    /* local_cseq is set to response->cseq->number for better
       handling of bad UA */
    (*dialog)->local_cseq = osip_atoi (response->cseq->number);
    (*dialog)->remote_cseq = osip_atoi (response->cseq->number);


    i = osip_from_clone (response->from, &((*dialog)->remote_uri));
    if (i != 0)
        goto diau_error_3;

    i = osip_to_clone (response->to, &((*dialog)->local_uri));
    if (i != 0)
        goto diau_error_4;

    {
        osip_contact_t *contact;

        if (!osip_list_eol (invite->contacts, 0))
        {
            contact = osip_list_get (invite->contacts, 0);
            i = osip_contact_clone (contact, &((*dialog)->remote_contact_uri));
            if (i != 0)
                goto diau_error_5;
        }
        else
        {
            (*dialog)->remote_contact_uri = NULL;
            OSIP_TRACE (osip_trace
                        (__FILE__, __LINE__, OSIP_WARNING, NULL,
                         "Remote UA is not compliant: missing a contact in response!\n"));
        }
    }
    (*dialog)->secure = -1;	/* non secure */

    return 0;

diau_error_5:
    osip_from_free ((*dialog)->local_uri);
diau_error_4:
    osip_from_free ((*dialog)->remote_uri);
diau_error_3:
diau_error_2:
    osip_list_special_free ((*dialog)->route_set,
                            (void *(*)(void *)) &osip_record_route_free);
    osip_free ((*dialog)->remote_tag);
    osip_free ((*dialog)->local_tag);
diau_error_1:
    osip_free ((*dialog)->call_id);
diau_error_0:
    OSIP_TRACE (osip_trace
                (__FILE__, __LINE__, OSIP_ERROR, NULL,
                 "Could not establish dialog!\n"));
    osip_free (*dialog);
    *dialog = NULL;
    return -1;
}
Пример #29
0
void
nist_snd_1xx (osip_transaction_t * nist, osip_event_t * evt)
{
  int i;
  osip_via_t *via;
  osip_t *osip = (osip_t *) nist->config;

  if (nist->last_response != NULL)
    {
      osip_message_free (nist->last_response);
    }
  nist->last_response = evt->sip;

  via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0);
  if (via)
    {
      char *host;
      int port;
      osip_generic_param_t *maddr;
      osip_generic_param_t *received;
      osip_generic_param_t *rport;
      osip_via_param_get_byname (via, "maddr", &maddr);
      osip_via_param_get_byname (via, "received", &received);
      osip_via_param_get_byname (via, "rport", &rport);
      /* 1: user should not use the provided information
         (host and port) if they are using a reliable
         transport. Instead, they should use the already
         open socket attached to this transaction. */
      /* 2: check maddr and multicast usage */
      if (maddr != NULL)
	host = maddr->gvalue;
      /* we should check if this is a multicast address and use
         set the "ttl" in this case. (this must be done in the
         UDP message (not at the SIP layer) */
      else if (received != NULL)
	host = received->gvalue;
      else
	host = via->host;

      if (rport == NULL || rport->gvalue == NULL)
	{
	  if (via->port != NULL)
	    port = osip_atoi (via->port);
	  else
	    port = 5060;
	}
      else
	port = osip_atoi (rport->gvalue);
      i = osip->cb_send_message (nist, nist->last_response, host,
				 port, nist->out_socket);
    }
  else
    i = -1;
  if (i != 0)
    {
      nist_handle_transport_error (nist, i);
      return;
    }
  else
    __osip_message_callback (OSIP_NIST_STATUS_1XX_SENT, nist, nist->last_response);

  __osip_transaction_set_state (nist, NIST_PROCEEDING);
}
Пример #30
0
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}
    };
    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);
      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);
      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;
}