int _eXosip_notify_set_refresh_interval (eXosip_notify_t * jn, osip_message_t * inc_subscribe) { osip_header_t *exp; time_t now; now = time (NULL); if (jn == NULL || inc_subscribe == NULL) return -1; osip_message_get_expires (inc_subscribe, 0, &exp); if (exp == NULL || exp->hvalue == NULL) jn->n_ss_expires = now + 600; else { jn->n_ss_expires = osip_atoi (exp->hvalue); if (jn->n_ss_expires != -1) jn->n_ss_expires = now + jn->n_ss_expires; else /* on error, set it to default */ jn->n_ss_expires = now + 600; } return 0; }
int _eXosip_subscribe_set_refresh_interval (eXosip_subscribe_t * js, osip_message_t * out_subscribe) { osip_header_t *exp; if (js == NULL || out_subscribe == NULL) return OSIP_BADPARAMETER; osip_message_get_expires (out_subscribe, 0, &exp); if (exp != NULL && exp->hvalue != NULL) { js->s_reg_period = osip_atoi (exp->hvalue); if (js->s_reg_period < 0) js->s_reg_period = 3600; } return OSIP_SUCCESS; }
int _eXosip_subscribe_set_refresh_interval(eXosip_subscribe_t *js, osip_message_t *out_subscribe) { osip_header_t *exp; time_t now = time(NULL); if (js==NULL || out_subscribe==NULL) return -1; osip_message_get_expires(out_subscribe, 0, &exp); if (exp==NULL || exp->hvalue==NULL) js->s_ss_expires = now + atoi(eXosip.subscribe_timeout); else { js->s_ss_expires = osip_atoi(exp->hvalue); if (js->s_ss_expires!=-1) js->s_ss_expires = now + js->s_ss_expires; else /* on error, set it to default */ js->s_ss_expires = now + atoi(eXosip.subscribe_timeout); } return 0; }
/* * set expiration timeout as received with SIP response * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */ int register_set_expire(sip_ticket_t *ticket) { int i, j; int expires=-1; osip_contact_t *contact=NULL; time_t time_now; osip_header_t *expires_hdr=NULL; osip_uri_param_t *expires_param=NULL; if (ticket->direction != RESTYP_INCOMING) { WARN("register_set_expire called with != incoming response"); return STS_FAILURE; } time(&time_now); DEBUGC(DBCLASS_REG,"REGISTER response, looking for 'Expire' information"); /* evaluate Expires Header field */ osip_message_get_expires(ticket->sipmsg, 0, &expires_hdr); /* loop for all existing contact headers in message */ for (j=0; (contact != NULL) || (j==0); j++) { osip_message_get_contact(ticket->sipmsg, j, &contact); /* * look for an Contact expires parameter - in case of REGISTER * these two are equal. The Contact expires has higher priority! */ if (contact==NULL) continue; osip_contact_param_get_byname(contact, EXPIRES, &expires_param); if (expires_param && expires_param->gvalue) { /* get expires from contact Header */ expires=atoi(expires_param->gvalue); if ((expires < 0) || (expires >= UINT_MAX )) expires=configuration.default_expires; } else if (expires_hdr && expires_hdr->hvalue) { /* get expires from expires Header */ expires=atoi(expires_hdr->hvalue); if ((expires < 0) || (expires >= UINT_MAX )) expires=configuration.default_expires; } DEBUGC(DBCLASS_REG,"Expires=%i, expires_param=%p, expires_hdr=%p", expires, expires_param, expires_hdr); if (expires > 0) { /* search for an entry */ for (i=0;i<URLMAP_SIZE;i++){ if (urlmap[i].active == 0) continue; if ((compare_url(contact->url, urlmap[i].masq_url)==STS_SUCCESS)) break; } /* found a mapping entry */ if (i<URLMAP_SIZE) { /* update registration timeout */ DEBUGC(DBCLASS_REG,"changing registration timeout to %i" " entry [%i]", expires, i); urlmap[i].expires=time_now+expires; } else { DEBUGC(DBCLASS_REG,"no urlmap entry found"); } } } /* for j */ return STS_SUCCESS; }
/* * send answer to a registration request. * flag = STS_SUCCESS -> positive answer (200) * flag = STS_FAILURE -> negative answer (503) * flag = STS_NEED_AUTH -> proxy authentication needed (407) * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */ int register_response(sip_ticket_t *ticket, int flag) { osip_message_t *response; int code; int sts; osip_via_t *via; int port; char *buffer; size_t buflen; struct in_addr addr; osip_header_t *expires_hdr; /* ok -> 200, fail -> 503 */ switch (flag) { case STS_SUCCESS: code = 200; /* OK */ break; case STS_FAILURE: code = 503; /* failed */ break; case STS_NEED_AUTH: code = 407; /* proxy authentication needed */ break; default: code = 503; /* failed */ break; } /* create the response template */ if ((response=msg_make_template_reply(ticket, code))==NULL) { ERROR("register_response: error in msg_make_template_reply"); return STS_FAILURE; } /* insert the expiration header */ osip_message_get_expires(ticket->sipmsg, 0, &expires_hdr); if (expires_hdr) { osip_message_set_expires(response, expires_hdr->hvalue); } /* if we send back an proxy authentication needed, include the Proxy-Authenticate field */ if (code == 407) { auth_include_authrq(response); } /* get the IP address from existing VIA header */ osip_message_get_via (response, 0, &via); if (via == NULL) { ERROR("register_response: Cannot send response - no via field"); return STS_FAILURE; } /* name resolution needed? */ if (utils_inet_aton(via->host,&addr) == 0) { /* yes, get IP address */ sts = get_ip_by_host(via->host, &addr); if (sts == STS_FAILURE) { DEBUGC(DBCLASS_REG, "register_response: cannot resolve VIA [%s]", via->host); return STS_FAILURE; } } sts = sip_message_to_str(response, &buffer, &buflen); if (sts != 0) { ERROR("register_response: msg_2char failed"); return STS_FAILURE; } /* send answer back */ if (via->port) { port=atoi(via->port); if ((port<=0) || (port>65535)) port=SIP_PORT; } else { port=configuration.sip_listen_port; } sipsock_send(addr, port, ticket->protocol, buffer, buflen); /* free the resources */ osip_message_free(response); free(buffer); return STS_SUCCESS; }
/* * handles register requests and updates the URL mapping table * * RETURNS: * STS_SUCCESS : successfully registered * STS_FAILURE : registration failed * STS_NEED_AUTH : authentication needed */ int register_client(sip_ticket_t *ticket, int force_lcl_masq) { int i, j, n, sts; int expires; time_t time_now; osip_contact_t *contact; osip_uri_t *url1_to, *url1_contact=NULL; osip_uri_t *url2_to; osip_header_t *expires_hdr; osip_uri_param_t *expires_param=NULL; /* * Authorization - do only if I'm not just acting as outbound proxy * but am ment to be the registrar */ if (force_lcl_masq == 0) { /* * RFC 3261, Section 16.3 step 6 * Proxy Behavior - Request Validation - Proxy-Authorization */ sts = authenticate_proxy(ticket->sipmsg); if (sts == STS_FAILURE) { /* failed */ WARN("proxy authentication failed for %s@%s", (ticket->sipmsg->to->url->username)? ticket->sipmsg->to->url->username : "******", ticket->sipmsg->to->url->host); return STS_FAILURE; } else if (sts == STS_NEED_AUTH) { /* needed */ DEBUGC(DBCLASS_REG,"proxy authentication needed for %s@%s", ticket->sipmsg->to->url->username, ticket->sipmsg->to->url->host); return STS_NEED_AUTH; } } /* fetch 1st Via entry and remember this address. Incoming requests for the registered address have to be passed on to that host. To: -> address to be registered Contact: -> host is reachable there Note: in case of un-REGISTER, the contact header may contain '*' only - which means "all registrations made by this UA" => Mapping is To: <1--n> Contact */ time(&time_now); DEBUGC(DBCLASS_BABBLE,"sip_register:"); /* * First make sure, we have a proper Contact header: * - url * - url -> hostname * * Libosip parses an: * "Contact: *" * the following way (Note: Display name!! and URL is NULL) * (gdb) p *((osip_contact_t*)(sip->contacts.node->element)) * $5 = {displayname = 0x8af8848 "*", url = 0x0, gen_params = 0x8af8838} */ osip_message_get_contact(ticket->sipmsg, 0, &contact); if ((contact == NULL) || (contact->url == NULL) || (contact->url->host == NULL)) { /* Don't have required Contact fields. This may be a Registration query or unregistering all registered records for this UA. We should simply forward this request to its destination. However, if this is an unregistration from a client that is not registered (Grandstream "unregister at startup" option) -> How do I handle this one? Right now we do a direction lookup and if this fails we generate an OK message by ourself (fake) */ DEBUGC(DBCLASS_REG, "empty Contact header - " "seems to be a registration query"); sts = sip_find_direction(ticket, NULL); if (sts != STS_SUCCESS) { /* answer the request myself. Most likely this is an UNREGISTER * request when the client just booted */ sts = register_response(ticket, STS_SUCCESS); return STS_SIP_SENT; } return STS_SUCCESS; } url1_contact=contact->url; /* evaluate Expires Header field */ osip_message_get_expires(ticket->sipmsg, 0, &expires_hdr); /* * look for an Contact expires parameter - in case of REGISTER * these two are equal. The Contact expires has higher priority! */ if (ticket->sipmsg->contacts.node && ticket->sipmsg->contacts.node->element) { osip_contact_param_get_byname( (osip_contact_t*) ticket->sipmsg->contacts.node->element, EXPIRES, &expires_param); } if (expires_param && expires_param->gvalue) { /* get expires from contact Header */ expires=atoi(expires_param->gvalue); if ((expires < 0) || (expires >= UINT_MAX )) expires=configuration.default_expires; } else if (expires_hdr && expires_hdr->hvalue) { /* get expires from expires Header */ expires=atoi(expires_hdr->hvalue); if ((expires < 0) || (expires >= UINT_MAX )) expires=configuration.default_expires; } else { char tmp[16]; /* it seems, the expires field is not present everywhere... */ DEBUGC(DBCLASS_REG,"no 'expires' header found - set time to %i sec", configuration.default_expires); expires=configuration.default_expires; sprintf(tmp,"%i",expires); osip_message_set_expires(ticket->sipmsg, tmp); } url1_to=ticket->sipmsg->to->url; /* * REGISTER */ if (expires > 0) { DEBUGC(DBCLASS_REG,"register: %s@%s expires=%i seconds", (url1_contact->username) ? url1_contact->username : "******", (url1_contact->host) ? url1_contact->host : "*NULL*", expires); /* * Update registration. There are two possibilities: * - already registered, then update the existing record * - not registered, then create a new record */ j=-1; for (i=0; i<URLMAP_SIZE; i++) { if (urlmap[i].active == 0) { if (j < 0) j=i; /* remember first hole */ continue; } url2_to=urlmap[i].reg_url; /* check address-of-record ("public address" of user) */ if (compare_url(url1_to, url2_to)==STS_SUCCESS) { DEBUGC(DBCLASS_REG, "found entry for %s@%s <-> %s@%s at " "slot=%i, exp=%li", (url1_contact->username) ? url1_contact->username : "******", (url1_contact->host) ? url1_contact->host : "*NULL*", (url2_to->username) ? url2_to->username : "******", (url2_to->host) ? url2_to->host : "*NULL*", i, (long)urlmap[i].expires-time_now); break; } } if ( (j < 0) && (i >= URLMAP_SIZE) ) { /* oops, no free entries left... */ ERROR("URLMAP is full - registration failed"); return STS_FAILURE; } if (i >= URLMAP_SIZE) { /* entry not existing, create new one */ i=j; /* write entry */ urlmap[i].active=1; /* Contact: field */ osip_uri_clone( ((osip_contact_t*) (ticket->sipmsg->contacts.node->element))->url, &urlmap[i].true_url); /* To: field */ osip_uri_clone( ticket->sipmsg->to->url, &urlmap[i].reg_url); DEBUGC(DBCLASS_REG,"create new entry for %s@%s <-> %s@%s at slot=%i", (url1_contact->username) ? url1_contact->username : "******", (url1_contact->host) ? url1_contact->host : "*NULL*", (urlmap[i].reg_url->username) ? urlmap[i].reg_url->username : "******", (urlmap[i].reg_url->host) ? urlmap[i].reg_url->host : "*NULL*", i); /* * try to figure out if we ought to do some masquerading */ osip_uri_clone( ticket->sipmsg->to->url, &urlmap[i].masq_url); n=configuration.mask_host.used; if (n != configuration.masked_host.used) { ERROR("# of mask_host is not equal to # of masked_host in config!"); n=0; } DEBUG("%i entries in MASK config table", n); for (j=0; j<n; j++) { DEBUG("compare [%s] <-> [%s]",configuration.mask_host.string[j], ticket->sipmsg->to->url->host); if (strcmp(configuration.mask_host.string[j], ticket->sipmsg->to->url->host)==0) break; } if (j<n) { /* we are masquerading this UA, replace the host part of the url */ DEBUGC(DBCLASS_REG,"masquerading UA %s@%s as %s@%s", (url1_contact->username) ? url1_contact->username : "******", (url1_contact->host) ? url1_contact->host : "*NULL*", (url1_contact->username) ? url1_contact->username : "******", configuration.masked_host.string[j]); urlmap[i].masq_url->host=realloc(urlmap[i].masq_url->host, strlen(configuration.masked_host.string[j])+1); strcpy(urlmap[i].masq_url->host, configuration.masked_host.string[j]); } } else { /* if new entry */ /* This is an existing entry */ /* * Some phones (like BudgeTones *may* dynamically grab a SIP port * so we might want to update the true_url and reg_url each time * we get an REGISTER */ /* Contact: field (true_url) */ osip_uri_free(urlmap[i].true_url); osip_uri_clone( ((osip_contact_t*) (ticket->sipmsg->contacts.node->element))->url, &urlmap[i].true_url); /* To: field (reg_url) */ osip_uri_free(urlmap[i].reg_url); osip_uri_clone( ticket->sipmsg->to->url, &urlmap[i].reg_url); } /* * for proxying: force device to be masqueraded * as with the outbound IP (masq_url) */ if (force_lcl_masq) { struct in_addr addr; char *addrstr; if (get_interface_ip(IF_OUTBOUND, &addr) != STS_SUCCESS) { return STS_FAILURE; } /* host part */ addrstr = utils_inet_ntoa(addr); DEBUGC(DBCLASS_REG,"masquerading UA %s@%s local %s@%s", (url1_contact->username) ? url1_contact->username : "******", (url1_contact->host) ? url1_contact->host : "*NULL*", (url1_contact->username) ? url1_contact->username : "******", addrstr); urlmap[i].masq_url->host=realloc(urlmap[i].masq_url->host, strlen(addrstr)+1); strcpy(urlmap[i].masq_url->host, addrstr); /* port number if required */ if (configuration.sip_listen_port != SIP_PORT) { urlmap[i].masq_url->port=realloc(urlmap[i].masq_url->port, 16); sprintf(urlmap[i].masq_url->port, "%i", configuration.sip_listen_port); } } /* give some safety margin for the next update */ if (expires > 0) expires+=30; /* update registration timeout */ urlmap[i].expires=time_now+expires; /* * un-REGISTER */ } else { /* expires > 0 */ /* * Remove registration * Siproxd will ALWAYS remove ALL bindings for a given * address-of-record */ for (i=0; i<URLMAP_SIZE; i++) { if (urlmap[i].active == 0) continue; url2_to=urlmap[i].reg_url; if (compare_url(url1_to, url2_to)==STS_SUCCESS) { DEBUGC(DBCLASS_REG, "removing registration for %s@%s at slot=%i", (url2_to->username) ? url2_to->username : "******", (url2_to->host) ? url2_to->host : "*NULL*", i); urlmap[i].expires=0; break; } } } return STS_SUCCESS; }
int _eXosip_build_response_default (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 -1; i = osip_message_init (&response); if (i != 0) return -1; /* initialise osip_message_t structure */ /* yet done... */ response->sip_version = (char *) osip_malloc (8 * sizeof (char)); sprintf (response->sip_version, "SIP/2.0"); osip_message_set_status_code (response, status); /* handle some internal reason definitions. */ if (MSG_IS_NOTIFY (request) && status == 481) { response->reason_phrase = osip_strdup ("Subcription 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; } i = osip_to_clone (request->to, &(response->to)); if (i != 0) goto grd_error_1; 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, osip_to_tag_new_random ()); } } i = osip_from_clone (request->from, &(response->from)); if (i != 0) goto grd_error_1; 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) goto grd_error_1; osip_list_add (response->vias, via2, -1); pos++; } i = osip_call_id_clone (request->call_id, &(response->call_id)); if (i != 0) goto grd_error_1; i = osip_cseq_clone (request->cseq, &(response->cseq)); if (i != 0) goto grd_error_1; 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); } } osip_message_set_allow (response, "INVITE"); osip_message_set_allow (response, "ACK"); osip_message_set_allow (response, "OPTIONS"); osip_message_set_allow (response, "CANCEL"); osip_message_set_allow (response, "BYE"); osip_message_set_allow (response, "SUBSCRIBE"); osip_message_set_allow (response, "NOTIFY"); osip_message_set_allow (response, "MESSAGE"); osip_message_set_allow (response, "INFO"); osip_message_set_allow (response, "REFER"); osip_message_set_allow (response, "UPDATE"); *dest = response; return 0; grd_error_1: osip_message_free (response); return -1; }
int eXosip_publish (struct eXosip_t *excontext, osip_message_t * message, const char *to) { osip_transaction_t *transaction; osip_event_t *sipevent; int i; eXosip_pub_t *pub = NULL; if (message == NULL) return OSIP_BADPARAMETER; if (message->cseq == NULL || message->cseq->number == NULL) { osip_message_free (message); return OSIP_SYNTAXERROR; } if (to == NULL) { osip_message_free (message); return OSIP_BADPARAMETER; } i = _eXosip_pub_find_by_aor (excontext, &pub, to); if (i != 0 || pub == NULL) { osip_header_t *expires; osip_message_get_expires (message, 0, &expires); if (expires == NULL || expires->hvalue == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: missing expires header in PUBLISH!")); osip_message_free (message); return OSIP_SYNTAXERROR; } else { /* start a new publication context */ i = _eXosip_pub_init (&pub, to, expires->hvalue); if (i != 0) { osip_message_free (message); return i; } ADD_ELEMENT (excontext->j_pub, pub); } } else { if (pub->p_sip_etag[0] != '\0') { /* increase cseq */ osip_message_set_header (message, "SIP-If-Match", pub->p_sip_etag); } { osip_header_t *expires; osip_message_get_expires (message, 0, &expires); if (expires == NULL || expires->hvalue == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: missing expires header in PUBLISH!")); osip_message_free (message); return OSIP_SYNTAXERROR; } pub->p_period = atoi (expires->hvalue); } if (pub->p_last_tr != NULL && pub->p_last_tr->cseq != NULL && pub->p_last_tr->cseq->number != NULL) { int osip_cseq_num = osip_atoi (pub->p_last_tr->cseq->number); int length = (int) strlen (pub->p_last_tr->cseq->number); osip_cseq_num++; osip_free (message->cseq->number); message->cseq->number = (char *) osip_malloc (length + 2); /* +2 like for 9 to 10 */ if (message->cseq->number == NULL) { osip_message_free (message); return OSIP_NOMEM; } snprintf (message->cseq->number, length + 2, "%i", osip_cseq_num); } } i = _eXosip_transaction_init (excontext, &transaction, NICT, excontext->j_osip, message); if (i != 0) { osip_message_free (message); return i; } if (pub->p_last_tr != NULL) osip_list_add (&excontext->j_transactions, pub->p_last_tr, 0); pub->p_last_tr = transaction; sipevent = osip_new_outgoing_sipmessage (message); sipevent->transactionid = transaction->transactionid; osip_transaction_add_event (transaction, sipevent); _eXosip_wakeup (excontext); return transaction->transactionid; }
int _eXosip_subscribe_automatic_refresh (struct eXosip_t *excontext, eXosip_subscribe_t * js, eXosip_dialog_t * jd, osip_transaction_t * out_tr) { osip_message_t *sub = NULL; osip_header_t *expires; int i; if (js == NULL || jd == NULL || out_tr == NULL || out_tr->orig_request == NULL) return OSIP_BADPARAMETER; i = eXosip_subscribe_build_refresh_request (excontext, jd->d_id, &sub); if (i != 0) return i; i = osip_message_get_expires (out_tr->orig_request, 0, &expires); if (expires != NULL && expires->hvalue != NULL) { osip_message_set_expires (sub, expires->hvalue); } { int pos = 0; osip_accept_t *_accept = NULL; i = osip_message_get_accept (out_tr->orig_request, pos, &_accept); while (i >= 0 && _accept != NULL) { osip_accept_t *_accept2; i = osip_accept_clone (_accept, &_accept2); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Error in Accept header\n")); break; } osip_list_add (&sub->accepts, _accept2, -1); _accept = NULL; pos++; i = osip_message_get_accept (out_tr->orig_request, pos, &_accept); } } { int pos = 0; osip_header_t *_event = NULL; pos = osip_message_header_get_byname (out_tr->orig_request, "Event", 0, &_event); while (pos >= 0 && _event != NULL) { osip_header_t *_event2; i = osip_header_clone (_event, &_event2); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Error in Event header\n")); break; } osip_list_add (&sub->headers, _event2, -1); _event = NULL; pos++; pos = osip_message_header_get_byname (out_tr->orig_request, "Event", pos, &_event); } } i = eXosip_subscribe_send_refresh_request (excontext, jd->d_id, sub); return i; }
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 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; } { osip_list_iterator_t it; osip_via_t *via = (osip_via_t*)osip_list_get_first(&request->vias, &it); while (via != NULL) { osip_via_t *via2; i = osip_via_clone (via, &via2); if (i != 0) { osip_message_free (response); return i; } osip_list_add (&response->vias, via2, -1); via = (osip_via_t *)osip_list_get_next(&it); } } 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; }