/* * 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", ¶m); 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, ¶m); if (param && param->gvalue) { MD5Update(&Md5Ctx, param->gvalue, strlen(param->gvalue)); } /* Tag in From header */ osip_from_get_tag(sip_msg->from, ¶m); 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; }
/* 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; }
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); }
/* 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; }
/* 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; }
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, ©); 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; }
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; }
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; }
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, ©); 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; }
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; }
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; }
/* 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; }
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; }
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; }
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; }
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; }
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; }
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; }
/* 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; }
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; } }
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; }
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; }
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 */ }
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; }
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; }
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; }
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; }
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; }
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); }
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; }