static int _tcp_tl_connect_socket (char *host, int port) { int pos; int res; struct addrinfo *addrinfo = NULL; struct addrinfo *curinfo; int sock = -1; char src6host[NI_MAXHOST]; memset (src6host, 0, sizeof (src6host)); for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (tcp_socket_tab[pos].socket == 0) { break; } } if (pos == EXOSIP_MAX_SOCKETS) return -1; res = eXosip_get_addrinfo (&addrinfo, host, port, IPPROTO_TCP); if (res) return -1; for (curinfo = addrinfo; curinfo; curinfo = curinfo->ai_next) { if (curinfo->ai_protocol && curinfo->ai_protocol != IPPROTO_TCP) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "eXosip: Skipping protocol %d\n", curinfo->ai_protocol)); continue; } res = getnameinfo ((struct sockaddr *) curinfo->ai_addr, curinfo->ai_addrlen, src6host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (res == 0) { int i = _tcp_tl_find_socket (src6host, port); if (i>=0) { eXosip_freeaddrinfo (addrinfo); return i; } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "New binding with %s\n", src6host)); } sock = (int) socket (curinfo->ai_family, curinfo->ai_socktype, curinfo->ai_protocol); if (sock < 0) { #if !defined(OSIP_MT) || defined(_WIN32_WCE) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "eXosip: Cannot create socket!\n")); #else OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "eXosip: Cannot create socket %s!\n", strerror (errno))); #endif continue; } if (curinfo->ai_family == AF_INET6) { #ifdef IPV6_V6ONLY if (setsockopt_ipv6only (sock)) { close (sock); sock = -1; #if !defined(OSIP_MT) || defined(_WIN32_WCE) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "eXosip: Cannot set socket option!\n")); #else OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "eXosip: Cannot set socket option %s!\n", strerror (errno))); #endif continue; } #endif /* IPV6_V6ONLY */ } res = connect (sock, curinfo->ai_addr, curinfo->ai_addrlen); if (res < 0) { #if !defined(OSIP_MT) || defined(_WIN32_WCE) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "eXosip: Cannot bind socket node:%s family:%d\n", host, curinfo->ai_family)); #else OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "eXosip: Cannot bind socket node:%s family:%d %s\n", host, curinfo->ai_family, strerror (errno))); #endif close (sock); sock = -1; continue; } break; } eXosip_freeaddrinfo (addrinfo); if (sock > 0) { tcp_socket_tab[pos].socket = sock; if (src6host[0]=='\0') osip_strncpy (tcp_socket_tab[pos].remote_ip, host, sizeof (tcp_socket_tab[pos].remote_ip) - 1); else osip_strncpy (tcp_socket_tab[pos].remote_ip, src6host, sizeof (tcp_socket_tab[pos].remote_ip) - 1); tcp_socket_tab[pos].remote_port = port; return sock; } return -1; }
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 (®, tr) == 0) { memcpy (&(reg->addr), &addr, len); reg->len = len; } } } osip_free (message); return OSIP_SUCCESS; }
static int udp_tl_open (void) { int res; struct addrinfo *addrinfo = NULL; struct addrinfo *curinfo; int sock = -1; if (eXtl_udp.proto_port < 0) eXtl_udp.proto_port = 5060; res = eXosip_get_addrinfo (&addrinfo, eXtl_udp.proto_ifs, eXtl_udp.proto_port, eXtl_udp.proto_num); if (res) return -1; for (curinfo = addrinfo; curinfo; curinfo = curinfo->ai_next) { socklen_t len; if (curinfo->ai_protocol && curinfo->ai_protocol != eXtl_udp.proto_num) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "eXosip: Skipping protocol %d\n", curinfo->ai_protocol)); continue; } sock = (int) socket (curinfo->ai_family, curinfo->ai_socktype, curinfo->ai_protocol); if (sock < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot create socket %s!\n", strerror (errno))); continue; } if (curinfo->ai_family == AF_INET6) { #ifdef IPV6_V6ONLY if (setsockopt_ipv6only (sock)) { close (sock); sock = -1; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot set socket option %s!\n", strerror (errno))); continue; } #endif /* IPV6_V6ONLY */ } res = bind (sock, curinfo->ai_addr, curinfo->ai_addrlen); if (res < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot bind socket node:%s family:%d %s\n", eXtl_udp.proto_ifs, curinfo->ai_family, strerror (errno))); close (sock); sock = -1; continue; } len = sizeof (ai_addr); res = getsockname (sock, (struct sockaddr *) &ai_addr, &len); if (res != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot get socket name (%s)\n", strerror (errno))); memcpy (&ai_addr, curinfo->ai_addr, curinfo->ai_addrlen); } if (eXtl_udp.proto_num != IPPROTO_UDP) { res = listen (sock, SOMAXCONN); if (res < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot bind socket node:%s family:%d %s\n", eXtl_udp.proto_ifs, curinfo->ai_family, strerror (errno))); close (sock); sock = -1; continue; } } break; } eXosip_freeaddrinfo (addrinfo); if (sock < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot bind on port: %i\n", eXtl_udp.proto_port)); return -1; } udp_socket = sock; if (eXtl_udp.proto_port == 0) { /* get port number from socket */ if (eXtl_udp.proto_family == AF_INET) eXtl_udp.proto_port = ntohs (((struct sockaddr_in *) &ai_addr)->sin_port); else eXtl_udp.proto_port = ntohs (((struct sockaddr_in6 *) &ai_addr)->sin6_port); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "eXosip: Binding on port %i!\n", eXtl_udp.proto_port)); } snprintf (udp_firewall_port, sizeof (udp_firewall_port), "%i", eXtl_udp.proto_port); return OSIP_SUCCESS; }
int _eXosip_build_request_within_dialog (osip_message_t ** dest, const char *method, osip_dialog_t * dialog, const char *transport) { int i; osip_message_t *request; char locip[65]; char firewall_ip[65]; char firewall_port[10]; *dest = NULL; if (dialog == NULL) return OSIP_BADPARAMETER; if (eXosip.eXtl == NULL) return OSIP_NO_NETWORK; if (eXosip.eXtl->tl_get_masquerade_contact != NULL) { eXosip.eXtl->tl_get_masquerade_contact (firewall_ip, sizeof (firewall_ip), firewall_port, sizeof (firewall_port)); } i = osip_message_init (&request); if (i != 0) return i; if (dialog->remote_contact_uri == NULL) { /* this dialog is probably not established! or the remote UA is not compliant with the latest RFC */ osip_message_free (request); return OSIP_SYNTAXERROR; } memset (locip, '\0', sizeof (locip)); eXosip_guess_ip_for_via (eXosip.eXtl->proto_family, locip, 49); if (locip[0] == '\0') { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: no default interface defined\n")); osip_message_free (request); return OSIP_NO_NETWORK; } /* prepare the request-line */ request->sip_method = osip_strdup (method); if (request->sip_method == NULL) { osip_message_free (request); return OSIP_NOMEM; } request->sip_version = osip_strdup ("SIP/2.0"); if (request->sip_version == NULL) { osip_message_free (request); return OSIP_NOMEM; } request->status_code = 0; request->reason_phrase = NULL; /* and the request uri???? */ if (osip_list_eol (&dialog->route_set, 0)) { /* The UAC must put the remote target URI (to field) in the req_uri */ i = osip_uri_clone (dialog->remote_contact_uri->url, &(request->req_uri)); if (i != 0) { osip_message_free (request); return i; } } else { /* fill the request-uri, and the route headers. */ i = dialog_fill_route_set (dialog, request); if (i != 0) { osip_message_free (request); return i; } } /* To and From already contains the proper tag! */ i = osip_to_clone (dialog->remote_uri, &(request->to)); if (i != 0) { osip_message_free (request); return i; } i = osip_from_clone (dialog->local_uri, &(request->from)); if (i != 0) { osip_message_free (request); return i; } /* set the cseq and call_id header */ osip_message_set_call_id (request, dialog->call_id); if (0 == strcmp ("ACK", method)) { osip_cseq_t *cseq; char *tmp; i = osip_cseq_init (&cseq); if (i != 0) { osip_message_free (request); return i; } tmp = osip_malloc (20); if (tmp == NULL) { osip_message_free (request); return OSIP_NOMEM; } sprintf (tmp, "%i", dialog->local_cseq); osip_cseq_set_number (cseq, tmp); osip_cseq_set_method (cseq, osip_strdup (method)); request->cseq = cseq; } else { osip_cseq_t *cseq; char *tmp; i = osip_cseq_init (&cseq); if (i != 0) { osip_message_free (request); return i; } dialog->local_cseq++; /* we should we do that?? */ tmp = osip_malloc (20); if (tmp == NULL) { osip_message_free (request); return OSIP_NOMEM; } sprintf (tmp, "%i", dialog->local_cseq); osip_cseq_set_number (cseq, tmp); osip_cseq_set_method (cseq, osip_strdup (method)); request->cseq = cseq; } /* always add the Max-Forward header */ osip_message_set_max_forwards (request, "70"); /* a UA should start a request with 70 */ i = _eXosip_request_add_via (request, transport, locip); if (i != 0) { osip_message_free (request); return i; } /* add specific headers for each kind of request... */ { char contact[200]; if (firewall_ip[0] != '\0') { char *c_address = request->req_uri->host; struct addrinfo *addrinfo; struct __eXosip_sockaddr addr; i = eXosip_get_addrinfo (&addrinfo, request->req_uri->host, 5060, IPPROTO_UDP); if (i == 0) { memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); eXosip_freeaddrinfo (addrinfo); c_address = inet_ntoa (((struct sockaddr_in *) &addr)->sin_addr); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "eXosip: here is the resolved destination host=%s\n", c_address)); } if (eXosip_is_public_address (c_address)) { sprintf (contact, "<sip:%s@%s:%s>", dialog->local_uri->url->username, firewall_ip, firewall_port); } else { sprintf (contact, "<sip:%s@%s:%s>", dialog->local_uri->url->username, locip, firewall_port); } } else { sprintf (contact, "<sip:%s@%s:%s>", dialog->local_uri->url->username, locip, firewall_port); } osip_message_set_contact (request, contact); /* Here we'll add the supported header if it's needed! */ /* the require header must be added by the upper layer if needed */ } if (0 == strcmp ("NOTIFY", method)) { } else if (0 == strcmp ("INFO", method)) { } else if (0 == strcmp ("OPTIONS", method)) { osip_message_set_accept (request, "application/sdp"); } else if (0 == strcmp ("ACK", method)) { /* The ACK MUST contains the same credential than the INVITE!! */ /* TODO... */ } osip_message_set_user_agent (request, eXosip.user_agent); /* else if ... */ *dest = request; return OSIP_SUCCESS; }
int _eXosip_dialog_add_contact (osip_message_t * request, osip_message_t * answer) { osip_via_t *via; osip_from_t *a_from; char *contact = NULL; char locip[65]; char firewall_ip[65]; char firewall_port[10]; int len; if (eXosip.eXtl == NULL) return OSIP_NO_NETWORK; if (request == NULL) return OSIP_BADPARAMETER; if (eXosip.eXtl->tl_get_masquerade_contact != NULL) { eXosip.eXtl->tl_get_masquerade_contact (firewall_ip, sizeof (firewall_ip), firewall_port, sizeof (firewall_port)); } /* search for topmost Via which indicate the transport protocol */ via = (osip_via_t *) osip_list_get (&request->vias, 0); if (via == NULL || via->protocol == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: missing via header\n")); return OSIP_SYNTAXERROR; } if (answer == NULL) a_from = request->from; else a_from = answer->to; if (a_from == NULL || a_from->url == NULL) return OSIP_SYNTAXERROR; /*guess the local ip since req uri is known */ memset (locip, '\0', sizeof (locip)); if (a_from->url->username != NULL) len = 2 + 4 + strlen (a_from->url->username) + 1 + 100 + 6 + 10 + strlen (eXosip.transport); else len = 2 + 4 + 100 + 6 + 10 + strlen (eXosip.transport); contact = (char *) osip_malloc (len + 1); if (contact == NULL) return OSIP_NOMEM; if (firewall_ip[0] != '\0') { char *c_address = request->req_uri->host; struct addrinfo *addrinfo; struct __eXosip_sockaddr addr; int i; i = eXosip_get_addrinfo (&addrinfo, request->req_uri->host, 5060, IPPROTO_TCP); if (i == 0) { memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); eXosip_freeaddrinfo (addrinfo); c_address = inet_ntoa (((struct sockaddr_in *) &addr)->sin_addr); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "eXosip: here is the resolved destination host=%s\n", c_address)); } if (eXosip_is_public_address (c_address)) { memcpy (locip, firewall_ip, sizeof (locip)); } } if (locip[0] == '\0') { eXosip_guess_ip_for_via (eXosip.eXtl->proto_family, locip, 49); if (locip[0] == '\0') { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: no default interface defined\n")); return OSIP_NO_NETWORK; } } if (eXosip.eXtl->proto_family == AF_INET6) { if (a_from->url->username != NULL) snprintf (contact, len, "<sip:%s@[%s]:%s>", a_from->url->username, locip, firewall_port); else snprintf (contact, len - strlen (eXosip.transport) - 10, "<sip:[%s]:%s>", locip, firewall_port); } else { if (a_from->url->username != NULL) snprintf (contact, len, "<sip:%s@%s:%s>", a_from->url->username, locip, firewall_port); else snprintf (contact, len - strlen (eXosip.transport) - 10, "<sip:%s:%s>", locip, firewall_port); } if (osip_strcasecmp (eXosip.transport, "UDP") != 0) { contact[strlen (contact) - 1] = '\0'; strcat (contact, ";transport="); strcat (contact, eXosip.transport); strcat (contact, ">"); } osip_message_set_contact (request, contact); osip_free (contact); return OSIP_SUCCESS; }
int complete_answer_that_establish_a_dialog (osip_message_t * response, osip_message_t * request) { int i; int pos = 0; char contact[1000]; char locip[50]; struct eXosip_net *net; /* 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 -1; osip_list_add (response->record_routes, rr2, -1); pos++; } i = _eXosip_find_protocol (response); if (i == IPPROTO_UDP) { net = &eXosip.net_interfaces[0]; } else if (i == IPPROTO_TCP) { net = &eXosip.net_interfaces[1]; } else { net = &eXosip.net_interfaces[0]; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: unsupported protocol (default to UDP)\n")); return -1; } #ifdef SM eXosip_get_localip_from_via (response, locip, 49); #else eXosip_guess_ip_for_via (net->net_ip_family, locip, 49); #endif if (request->to->url->username == NULL) snprintf (contact, 1000, "<sip:%s:%s>", locip, net->net_port); else snprintf (contact, 1000, "<sip:%s@%s:%s>", request->to->url->username, locip, net->net_port); if (eXosip.net_interfaces[0].net_firewall_ip[0] != '\0') { 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 (&addrinfo, con->url->host, 5060, IPPROTO_UDP); if (i == 0) { memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); 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>", eXosip.net_interfaces[0].net_firewall_ip, net->net_port); else snprintf (contact, 1000, "<sip:%s@%s:%s>", request->to->url->username, eXosip.net_interfaces[0].net_firewall_ip, net->net_port); } } } osip_message_set_contact (response, contact); return 0; }
int generating_register (eXosip_reg_t * jreg, osip_message_t ** reg, char *transport, char *from, char *proxy, char *contact, int expires) { int i; char locip[65]; char firewall_ip[65]; char firewall_port[10]; if (eXosip.eXtl == NULL) return OSIP_NO_NETWORK; if (eXosip.eXtl->tl_get_masquerade_contact != NULL) { eXosip.eXtl->tl_get_masquerade_contact (firewall_ip, sizeof (firewall_ip), firewall_port, sizeof (firewall_port)); } i = generating_request_out_of_dialog (reg, "REGISTER", NULL, transport, from, proxy); if (i != 0) return i; memset (locip, '\0', sizeof (locip)); eXosip_guess_ip_for_via (eXosip.eXtl->proto_family, locip, 49); if (locip[0] == '\0') { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: no default interface defined\n")); osip_message_free (*reg); *reg = NULL; return OSIP_NO_NETWORK; } if (contact == NULL) { osip_contact_t *new_contact = NULL; osip_uri_t *new_contact_url = NULL; i = osip_contact_init (&new_contact); if (i == 0) i = osip_uri_init (&new_contact_url); new_contact->url = new_contact_url; if (i == 0 && (*reg)->from != NULL && (*reg)->from->url != NULL && (*reg)->from->url->username != NULL) { new_contact_url->username = osip_strdup ((*reg)->from->url->username); } if (i == 0 && (*reg)->from != NULL && (*reg)->from->url != NULL) { /* serach for correct ip */ if (firewall_ip[0] != '\0') { char *c_address = (*reg)->req_uri->host; struct addrinfo *addrinfo; struct __eXosip_sockaddr addr; i = eXosip_get_addrinfo (&addrinfo, (*reg)->req_uri->host, 5060, IPPROTO_UDP); if (i == 0) { memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); eXosip_freeaddrinfo (addrinfo); c_address = inet_ntoa (((struct sockaddr_in *) &addr)->sin_addr); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "eXosip: here is the resolved destination host=%s\n", c_address)); } if (eXosip_is_public_address (c_address)) { new_contact_url->host = osip_strdup (firewall_ip); new_contact_url->port = osip_strdup (firewall_port); } else { new_contact_url->host = osip_strdup (locip); new_contact_url->port = osip_strdup (firewall_port); } } else { new_contact_url->host = osip_strdup (locip); new_contact_url->port = osip_strdup (firewall_port); } if (transport != NULL && osip_strcasecmp (transport, "UDP") != 0) { osip_uri_uparam_add (new_contact_url, osip_strdup ("transport"), osip_strdup (transport)); } if (jreg->r_line[0] != '\0') { osip_uri_uparam_add (new_contact_url, osip_strdup ("line"), osip_strdup (jreg->r_line)); } osip_list_add (&(*reg)->contacts, new_contact, -1); } } else { osip_message_set_contact (*reg, contact); } { char exp[10]; /* MUST never be ouside 1 and 3600 */ snprintf (exp, 9, "%i", expires); osip_message_set_expires (*reg, exp); } osip_message_set_content_length (*reg, "0"); return OSIP_SUCCESS; }
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(®, 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; }
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 (®, tr) == 0) { memcpy (&(reg->addr), &addr, len); reg->len = len; } } } osip_free (message); return 0; }
static int shutdown_free_client_dtls (int pos) { int i, err; BIO *rbio; struct addrinfo *addrinfo; struct __eXosip_sockaddr addr; if (dtls_socket_tab[pos].ssl_type == 2) { if (dtls_socket_tab[pos].ssl_conn != NULL) { i = eXosip_get_addrinfo (&addrinfo, dtls_socket_tab[pos].remote_ip, dtls_socket_tab[pos].remote_port, IPPROTO_UDP); if (i != 0) { return -1; } memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); eXosip_freeaddrinfo (addrinfo); rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (rbio, &addr); (dtls_socket_tab[pos].ssl_conn)->rbio = rbio; i = SSL_shutdown (dtls_socket_tab[pos].ssl_conn); if (i <= 0) { err = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i); #ifdef SSLDEBUG OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS client shutdown error %d <= 0\n", i)); #endif print_ssl_error (err); } else { #ifdef SSLDEBUG OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "DTLS client shutdown > 0\n")); #endif } SSL_free (dtls_socket_tab[pos].ssl_conn); #if 0 if (dtls_socket_tab[pos].ssl_ctx != NULL) SSL_CTX_free (dtls_socket_tab[pos].ssl_ctx); #endif memset (&(dtls_socket_tab[pos]), 0, sizeof (struct socket_tab)); return 0; } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS client shutdown: invalid SSL object!\n")); return -1; } } return -1; }
static int udp_tl_open(void) { int res; struct addrinfo *addrinfo = NULL; struct addrinfo *curinfo; int sock = -1; sockaddr_x *sa; if (eXtl_udp.proto_port < 0) eXtl_udp.proto_port = 5060; res = eXosip_get_addrinfo(&addrinfo, eXtl_udp.proto_ifs, eXtl_udp.proto_port, eXtl_udp.proto_num); if (res) return -1; for (curinfo = addrinfo; curinfo; curinfo = curinfo->ai_next) { socklen_t len; if (curinfo->ai_protocol && curinfo->ai_protocol != eXtl_udp.proto_num) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "eXosip: Skipping protocol %d\n", curinfo->ai_protocol)); continue; } /* sock = (int) socket(curinfo->ai_family, curinfo->ai_socktype, curinfo->ai_protocol); */ sock = (int) Xsocket(AF_XIA, SOCK_DGRAM, 0); if (sock < 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot create socket %s!\n", strerror(errno))); continue; } /* if (curinfo->ai_family == AF_INET6) { #ifdef IPV6_V6ONLY if (setsockopt_ipv6only(sock)) { close(sock); sock = -1; OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot set socket option %s!\n", strerror(errno))); continue; } #endif } */ /* res = bind(sock, curinfo->ai_addr, curinfo->ai_addrlen); */ sa = (sockaddr_x*)(curinfo->ai_addr); res = Xbind(sock, (struct sockaddr *)sa, sizeof(sockaddr_x)); if (res < 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot bind socket node:%s family:%d %s\n", eXtl_udp.proto_ifs, curinfo->ai_family, strerror(errno))); Xclose(sock); sock = -1; continue; } len = sizeof(ai_addr); /* res = getsockname(sock, (struct sockaddr *) &ai_addr, &len); */ res = Xgetsockname(sock, (struct sockaddr *) &ai_addr, &len); if (res != 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot get socket name (%s)\n", strerror(errno))); memcpy(&ai_addr, curinfo->ai_addr, curinfo->ai_addrlen); } /* if (eXtl_udp.proto_num != IPPROTO_UDP) { res = listen(sock, SOMAXCONN); if (res < 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot bind socket node:%s family:%d %s\n", eXtl_udp.proto_ifs, curinfo->ai_family, strerror(errno))); close(sock); sock = -1; continue; } } */ break; } eXosip_freeaddrinfo(addrinfo); /* Xfreeaddrinfo(addrinfo); */ if (sock < 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot bind on port: %i\n", eXtl_udp.proto_port)); return -1; } udp_socket = sock; /* if (eXtl_udp.proto_family == AF_INET) { int tos = (eXosip.dscp << 2) & 0xFC; res = setsockopt(udp_socket, IPPROTO_IP, IP_TOS, (SOCKET_OPTION_VALUE)&tos, sizeof(tos)); } else { int tos = (eXosip.dscp << 2) & 0xFC; #ifdef IPV6_TCLASS res = setsockopt(udp_socket, IPPROTO_IPV6, IPV6_TCLASS, (SOCKET_OPTION_VALUE)&tos, sizeof(tos)); #else res = setsockopt(udp_socket, IPPROTO_IPV6, IP_TOS, (SOCKET_OPTION_VALUE)&tos, sizeof(tos)); #endif } if (eXtl_udp.proto_port == 0) { get port number from socket if (eXtl_udp.proto_family == AF_INET) eXtl_udp.proto_port = ntohs(((struct sockaddr_in *) &ai_addr)->sin_port); else eXtl_udp.proto_port = ntohs(((struct sockaddr_in6 *) &ai_addr)->sin6_port); OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "eXosip: Binding on port %i!\n", eXtl_udp.proto_port)); } snprintf(udp_firewall_port, sizeof(udp_firewall_port), "%i", eXtl_udp.proto_port); */ return OSIP_SUCCESS; }
int complete_answer_that_establish_a_dialog (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]; if (eXosip.eXtl->tl_get_masquerade_contact != NULL) { eXosip.eXtl->tl_get_masquerade_contact (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 (eXosip.eXtl->proto_family, locip, 49); if (request->to->url->username == NULL) snprintf (contact, 1000, "<sip:%s:%s>", locip, firewall_port); else snprintf (contact, 1000, "<sip:%s@%s:%s>", request->to->url->username, locip, firewall_port); if (firewall_ip[0] != '\0') { 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 (&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 snprintf (contact, 1000, "<sip:%s@%s:%s>", request->to->url->username, firewall_ip, firewall_port); } } } { 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) < 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; }