Ejemplo n.º 1
0
static int
udp_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host,
					int port, int out_socket)
{
	int len = 0;
	size_t length = 0;
	struct addrinfo *addrinfo;
	struct __eXosip_sockaddr addr;
	char *message = NULL;

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

	if (udp_socket <= 0)
		return -1;

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

	eXtl_update_local_target(sip);

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

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

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

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

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

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

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

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

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

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

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

	eXosip_freeaddrinfo(addrinfo);

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

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

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

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

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

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

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

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

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

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

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

	osip_free(message);
	return OSIP_SUCCESS;
}
Ejemplo n.º 2
0
static int
udp_tl_send_message (osip_transaction_t * tr, osip_message_t * sip, char *host,
                     int port, int out_socket)
{
  int len = 0;
  size_t length = 0;
  struct addrinfo *addrinfo;
  struct __eXosip_sockaddr addr;
  char *message;
  char *crypt_date;
  char ipbuf[INET6_ADDRSTRLEN];
  int i;

  if (udp_socket <= 0)
    return -1;

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

  eXtl_update_local_target (sip);

  i = -1;
#ifndef MINISIZE
  if (tr != NULL && tr->record.name[0] != '\0'
      && tr->record.srventry[0].srv[0] != '\0')
    {
      /* always choose the first here.
         if a network error occur, remove first entry and
         replace with next entries.
       */
      osip_srv_entry_t *srv;
      int n = 0;
      for (srv = &tr->record.srventry[0];
           n < 10 && tr->record.srventry[0].srv[0]; srv = &tr->record.srventry[0])
        {
          i = eXosip_get_addrinfo (&addrinfo, srv->srv, srv->port, IPPROTO_UDP);
          if (i == 0)
            {
              host = srv->srv;
              port = srv->port;
              break;
            }
          memmove (&tr->record.srventry[0], &tr->record.srventry[1],
                   9 * sizeof (osip_srv_entry_t));
          memset (&tr->record.srventry[9], 0, sizeof (osip_srv_entry_t));
          i = -1;
          /* copy next element */
          n++;
        }
    }
#endif

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

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

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

  eXosip_freeaddrinfo (addrinfo);

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

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

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

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

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

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

  //SIP加密点

  crypt_date = (char *)malloc(length);

  memcpy(crypt_date,(const char *)message, length);

#ifdef ENABLE_MYCRYPT
  CRYPT_DATA_SIP((unsigned char *)crypt_date,length);
#endif // ENABLE_MYCRYPT

  if (0 >
      sendto (udp_socket, (const void *) crypt_date, length, 0,
              (struct sockaddr *) &addr, len))
    {
#ifdef WIN32
      if (WSAECONNREFUSED == WSAGetLastError ())
#else
      if (ECONNREFUSED == errno)
#endif
        {
          /* This can be considered as an error, but for the moment,
             I prefer that the application continue to try sending
             message again and again... so we are not in a error case.
             Nevertheless, this error should be announced!
             ALSO, UAS may not have any other options than retry always
             on the same port.
           */
          osip_free (message);
          return 1;
      } else
        {

#ifndef MINISIZE
          /* delete first SRV entry that is not reachable */
          if (tr != NULL && tr->record.name[0] != '\0'
              && tr->record.srventry[0].srv[0] != '\0')
            {
              memmove (&tr->record.srventry[0], &tr->record.srventry[1],
                       9 * sizeof (osip_srv_entry_t));
              memset (&tr->record.srventry[9], 0, sizeof (osip_srv_entry_t));
              osip_free (message);
              return OSIP_SUCCESS;      /* retry for next retransmission! */
            }
#endif
          /* SIP_NETWORK_ERROR; */
          osip_free (message);
          return -1;
        }
    }

  if (eXosip.keep_alive > 0)
    {
      if (MSG_IS_REGISTER (sip))
        {
          eXosip_reg_t *reg = NULL;

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

  osip_free (message);
  return OSIP_SUCCESS;
}
Ejemplo n.º 3
0
static int
dtls_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host,
                    int port, int out_socket)
{
  int len = 0;
  size_t length = 0;
  struct addrinfo *addrinfo;
  struct __eXosip_sockaddr addr;
  char *message;

  char ipbuf[INET6_ADDRSTRLEN];
  int i;

  int pos;
  struct socket_tab *socket_tab_used=NULL;
  BIO *sbio=NULL;

  if (dtls_socket <= 0)
    return -1;

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

  if (port == 5060)
    port = 5061;

  if (MSG_IS_REQUEST(sip))
    {
      if (MSG_IS_REGISTER(sip)
	  ||MSG_IS_INVITE(sip)
	  ||MSG_IS_SUBSCRIBE(sip)
	  || MSG_IS_NOTIFY(sip))
	eXtl_update_local_target(sip);
    }

  i=-1;
#ifndef MINISIZE
  if (tr!=NULL && tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0')
    {
      /* always choose the first here.
	 if a network error occur, remove first entry and
	 replace with next entries.
      */
      osip_srv_entry_t *srv;
      int n=0;
      for (srv = &tr->record.srventry[0];
	   n<10 && tr->record.srventry[0].srv[0];
	   srv = &tr->record.srventry[0])
	{
	  i = eXosip_get_addrinfo (&addrinfo, srv->srv, srv->port, IPPROTO_UDP);
	  if (i == 0)
	    {
	      host = srv->srv;
	      port = srv->port;
	      break;
	    }
	  memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t));
	  memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t));
	  i=-1;
	  /* copy next element */
	  n++;
	}
    }
#endif
  
  /* if SRV was used, distination may be already found */
  if (i != 0)
    {
      i = eXosip_get_addrinfo (&addrinfo, host, port, IPPROTO_UDP);
    }
  
  if (i != 0)
    {
      return -1;
    }
  
  memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
  len = addrinfo->ai_addrlen;
  
  eXosip_freeaddrinfo (addrinfo);
  
  /* remove preloaded route if there is no tag in the To header
   */
  {
    osip_route_t *route=NULL;
    osip_generic_param_t *tag=NULL;
    osip_message_get_route (sip, 0, &route);
    
    osip_to_get_tag (sip->to, &tag);
    if (tag==NULL && route != NULL && route->url != NULL)
      {
	osip_list_remove(&sip->routes, 0);
      }
    i = osip_message_to_str (sip, &message, &length);
    if (tag==NULL && route != NULL && route->url != NULL)
      {
	osip_list_add(&sip->routes, route, 0);
      }
  }
  
  if (i != 0 || length <= 0)
    {
      return -1;
    }
  
  switch ( ((struct sockaddr *)&addr)->sa_family )
    {
    case AF_INET:
      inet_ntop (((struct sockaddr *)&addr)->sa_family, &(((struct sockaddr_in *) &addr)->sin_addr),
		 ipbuf, sizeof (ipbuf));
      break;
    case AF_INET6:
      inet_ntop (((struct sockaddr *)&addr)->sa_family,
		 &(((struct sockaddr_in6 *) &addr)->sin6_addr), ipbuf,
		 sizeof (ipbuf));
      break;
    default:
      strncpy (ipbuf, "(unknown)", sizeof (ipbuf));
      break;
    }
  
  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
                          "Message sent: \n%s (to dest=%s:%i)\n",
                          message, ipbuf, port));

  for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++)
    {
      if (dtls_socket_tab[pos].ssl_conn != NULL
	  && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_SERVER)
	{
	  if (dtls_socket_tab[pos].remote_port == port &&
	      (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0))
	    {
	      BIO *rbio;
	      socket_tab_used = &dtls_socket_tab[pos];
	      rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE);
	      BIO_dgram_set_peer (rbio, &addr);
	      dtls_socket_tab[pos].ssl_conn->rbio = rbio;
	      break;
	    }
	}
    }
  if (socket_tab_used==NULL)
    {
      for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++)
	{
	  if (dtls_socket_tab[pos].ssl_conn != NULL
	      && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_CLIENT)
	    {
	      if (dtls_socket_tab[pos].remote_port == port &&
		  (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0))
		{
		  BIO *rbio;
		  socket_tab_used = &dtls_socket_tab[pos];
		  rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE);
		  BIO_dgram_set_peer (rbio, &addr);
		  dtls_socket_tab[pos].ssl_conn->rbio = rbio;
		  break;
		}
	    }
	}
    }

  if (socket_tab_used==NULL)
    {
      /* delete an old one! */
      pos=0;
      if (dtls_socket_tab[pos].ssl_conn != NULL)
	{
	  shutdown_free_client_dtls (pos);
	  shutdown_free_server_dtls (pos);
	}
      
      memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));
    }
  
  if (dtls_socket_tab[pos].ssl_conn == NULL)
    {
      /* create a new one */
      SSL_CTX_set_read_ahead (client_ctx, 1);
      dtls_socket_tab[pos].ssl_conn = SSL_new (client_ctx);

      if (dtls_socket_tab[pos].ssl_conn == NULL)
	{
	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
				  "DTLS SSL_new error\n"));

	  if (dtls_socket_tab[pos].ssl_conn != NULL)
	    {
	      shutdown_free_client_dtls (pos);
	      shutdown_free_server_dtls (pos);
	    }
	  
	  memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));

	  osip_free (message);
	  return -1;
	}

      if (connect (dtls_socket, (struct sockaddr *) &addr, sizeof (addr)) == -1)
	{
	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
				  "DTLS connect error\n"));
	  if (dtls_socket_tab[pos].ssl_conn != NULL)
	    {
	      shutdown_free_client_dtls (pos);
	      shutdown_free_server_dtls (pos);
	    }
	  
	  memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));

	  osip_free (message);
	  return -1;
	}
      
      SSL_set_options (dtls_socket_tab[pos].ssl_conn, SSL_OP_NO_QUERY_MTU);
      SSL_set_mtu (dtls_socket_tab[pos].ssl_conn, 2000);
      SSL_set_connect_state (dtls_socket_tab[pos].ssl_conn);
      sbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE);
      BIO_ctrl_set_connected (sbio, 1, (struct sockaddr *) &addr);
      SSL_set_bio (dtls_socket_tab[pos].ssl_conn, sbio, sbio);

      dtls_socket_tab[pos].ssl_type = 2;
      dtls_socket_tab[pos].ssl_state = 2;
      
      osip_strncpy (dtls_socket_tab[pos].remote_ip, ipbuf,
		    sizeof (dtls_socket_tab[pos].remote_ip));
      dtls_socket_tab[pos].remote_port = port;
    }

  i = SSL_write (dtls_socket_tab[pos].ssl_conn, message, length);

  if (i<0)
    {
      i = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i);
      print_ssl_error (i);
      if (i==SSL_ERROR_SSL
	  || i==SSL_ERROR_SYSCALL)
	{
	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
				  "DTLS SSL_write error\n"));
	  if (dtls_socket_tab[pos].ssl_conn != NULL)
	      {
		shutdown_free_client_dtls (pos);
		shutdown_free_server_dtls (pos);
	      }
	  
	  memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));
	  
	}

#ifndef MINISIZE
      /* delete first SRV entry that is not reachable */
      if (tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0')
	{
	  memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t));
	  memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t));
	  osip_free (message);
	  return 0; /* retry for next retransmission! */
	}
#endif
      /* SIP_NETWORK_ERROR; */
      osip_free (message);
      return -1;
    }

  if (eXosip.keep_alive > 0)
    {
      if (MSG_IS_REGISTER (sip))
        {
          eXosip_reg_t *reg = NULL;
	  
          if (_eXosip_reg_find (&reg, tr) == 0)
            {
              memcpy (&(reg->addr), &addr, len);
              reg->len = len;
            }
        }
    }
  
  osip_free (message);
  return 0;
}