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