ChordId Node::getPredWithContact(osip_message_t *M) { osip_contact_t *osip_contact ; osip_generic_param_t *param ; osip_message_get_contact(M,0,&osip_contact) ; int i = osip_contact_param_get_byname (osip_contact, "predecessor", ¶m); osip_uri_t *uri; i=osip_uri_init(&uri); if (i!=0) { fprintf(stderr, "cannot allocate\n"); return -1; } i=osip_uri_parse(uri, param->gvalue); if (i!=0) { fprintf(stderr, "cannot parse uri\n"); } ChordId new_predessor( atoi(uri->username), constants, uri->host, uri->port ) ; osip_uri_free(uri); return new_predessor ; }
/* * 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; }
/* * 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; }
/** * Processing the events, return the number of event happened. */ int jua_process_event(eXosipua_t *jua) { int counter =0; eXosip_event_t *je; for (;;) { char buf[100]; je = eXosip_event_wait(0,50); if (je==NULL) break; counter++; jua_debug(("jua_process_event: je->status_code[%d]\n", je->status_code)); if (je->type==EXOSIP_CALL_NEW) { jua_log(("jua_process_event: EXOSIP_CALL_NEW\n")); jcall_new(jua, je); } else if (je->type==EXOSIP_CALL_ANSWERED) { jua_log(("jua_process_event: EXOSIP_CALL_ANSWERED\n")); jcall_answered(jua, je); } else if (je->type==EXOSIP_CALL_ACK) { jua_log(("jua_process_event: EXOSIP_CALL_ACK\n")); jcall_ack(jua, je); } else if (je->type==EXOSIP_CALL_PROCEEDING) { jua_log(("jua_process_event: EXOSIP_CALL_PROCEEDING\n")); jcall_proceeding(jua, je); } else if (je->type==EXOSIP_CALL_RINGING) { jua_log(("jua_process_event: EXOSIP_CALL_RINGING\n")); jcall_ringing(jua, je); } else if (je->type==EXOSIP_CALL_REDIRECTED) { jua_log(("jua_process_event: EXOSIP_CALL_REDIRECTED\n")); jcall_redirected(jua, je); } else if (je->type==EXOSIP_CALL_REQUESTFAILURE) { jua_log(("jua_process_event: EXOSIP_CALL_REQUESTFAILURE\n")); jcall_requestfailure(jua, je); } else if (je->type==EXOSIP_CALL_SERVERFAILURE) { jua_log(("jua_process_event: EXOSIP_CALL_SERVERFAILURE\n")); jcall_serverfailure(jua, je); } else if (je->type==EXOSIP_CALL_GLOBALFAILURE) { jua_log(("jua_process_event: EXOSIP_CALL_GLOBALFAILURE\n")); jcall_globalfailure(jua, je); } else if (je->type==EXOSIP_CALL_CLOSED) { jua_log(("jua_process_event: EXOSIP_CALL_CLOSED\n")); jcall_closed(jua, je); } else if (je->type==EXOSIP_CALL_HOLD) { jua_log(("jua_process_event: EXOSIP_CALL_HOLD\n")); jcall_onhold(jua, je); } else if (je->type==EXOSIP_CALL_OFFHOLD) { jua_log(("jua_process_event: EXOSIP_CALL_OFFHOLD\n")); jcall_offhold(jua, je); } else if (je->type==EXOSIP_REGISTRATION_SUCCESS) { sipua_reg_event_t reg_e; eXosip_reg_t *jr; osip_message_t *message = NULL; reg_e.event.call_info = NULL; reg_e.event.type = SIPUA_EVENT_REGISTRATION_SUCCEEDED; reg_e.status_code = je->status_code; /* eg: 200*/ reg_e.server_info = je->reason_phrase; /* eg: OK */ reg_e.server = je->req_uri; /* eg: sip:registrar.domain */ /* je->remote_uri // eg: regname@domain */ /* * Retrieve exactly returned expiration seconds */ message = eXosipua_extract_message(jua, je); if(message) { osip_contact_t *contact = NULL; osip_message_get_contact(message, 0, &contact); if(contact) { osip_uri_param_t *expires = NULL; osip_contact_param_get_byname(contact, "expires", &expires); if(expires) reg_e.seconds_expires = strtol(expires->gvalue, NULL, 10); } osip_message_free(message); } else { jr = eXosip_event_get_reginfo(je); reg_e.seconds_expires = jr->r_reg_period; } /* snprintf(buf, 99, "<- (%i) [%i %s] %s for REGISTER %s", je->rid, je->status_code, je->reason_phrase, je->remote_uri, je->req_uri); printf("jua_process_event: reg ok! [%s]\n", buf); */ jua->registration_status = je->status_code; snprintf(jua->registration_server, 100, "%s", je->req_uri); if (je->reason_phrase!='\0') snprintf(jua->registration_reason_phrase, 100, "%s", je->reason_phrase); else jua->registration_reason_phrase[0] = '\0'; reg_e.event.from = jua->registration_server; reg_e.event.content = NULL; /* event back to sipuac */ jua->sipuas.notify_event(jua->sipuas.lisener, ®_e.event); } else if (je->type==EXOSIP_REGISTRATION_FAILURE) { sipua_reg_event_t reg_e; reg_e.event.type = SIPUA_EVENT_REGISTRATION_FAILURE; reg_e.status_code = je->status_code; reg_e.server_info = je->reason_phrase; reg_e.server = je->req_uri; reg_e.event.from = je->req_uri; reg_e.event.content = NULL; reg_e.event.call_info = NULL; /* event back to sipuac */ jua->sipuas.notify_event(jua->sipuas.lisener, ®_e.event); } else if (je->type==EXOSIP_OPTIONS_NEW) { int k; /* snprintf(buf, 99, "<- (%i %i) OPTIONS from: %s", je->cid, je->did, je->remote_uri); josua_printf(buf); */ /* answer the OPTIONS method */ /* 1: search for an existing call */ for (k=0;k<MAX_NUMBER_OF_CALLS;k++) { if (jua->jcalls[k].state != NOT_USED || jua->jcalls[k].cid==je->cid) break; } eXosip_lock(); if (jua->jcalls[k].cid==je->cid) { /* already answered! */ } else if (k==MAX_NUMBER_OF_CALLS) { /* answer 200 ok */ eXosip_answer_options(je->cid, je->did, 200); } else { /* answer 486 ok */ eXosip_answer_options(je->cid, je->did, 486); } eXosip_unlock(); } else if (je->type==EXOSIP_OPTIONS_ANSWERED) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_OPTIONS_PROCEEDING) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_OPTIONS_REDIRECTED) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_OPTIONS_REQUESTFAILURE) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_OPTIONS_SERVERFAILURE) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_OPTIONS_GLOBALFAILURE) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_INFO_NEW) { /* snprintf(buf, 99, "<- (%i %i) INFO from: %s", je->cid, je->did, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_INFO_ANSWERED) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_INFO_PROCEEDING) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_INFO_REDIRECTED) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_INFO_REQUESTFAILURE) { snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); /*josua_printf(buf);*/ } else if (je->type==EXOSIP_INFO_SERVERFAILURE) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_INFO_GLOBALFAILURE) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s", je->cid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ } else if (je->type==EXOSIP_SUBSCRIPTION_ANSWERED) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s for SUBSCRIBE", je->sid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); snprintf(buf, 99, "<- (%i %i) online=%i [status: %i reason:%i]", je->sid, je->did, je->online_status, je->ss_status, je->ss_reason); josua_printf(buf); */ jsubscription_answered(jua, je); } else if (je->type==EXOSIP_SUBSCRIPTION_PROCEEDING) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s for SUBSCRIBE", je->sid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ jsubscription_proceeding(jua, je); } else if (je->type==EXOSIP_SUBSCRIPTION_REDIRECTED) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s for SUBSCRIBE", je->sid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ jsubscription_redirected(jua, je); } else if (je->type==EXOSIP_SUBSCRIPTION_REQUESTFAILURE) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s for SUBSCRIBE", je->sid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ jsubscription_requestfailure(jua, je); } else if (je->type==EXOSIP_SUBSCRIPTION_SERVERFAILURE) { snprintf(buf, 99, "<- (%i %i) [%i %s] %s for SUBSCRIBE", je->sid, je->did, je->status_code, je->reason_phrase, je->remote_uri); /*josua_printf(buf);*/ jsubscription_serverfailure(jua, je); } else if (je->type==EXOSIP_SUBSCRIPTION_GLOBALFAILURE) { /* snprintf(buf, 99, "<- (%i %i) [%i %s] %s for SUBSCRIBE", je->sid, je->did, je->status_code, je->reason_phrase, je->remote_uri); josua_printf(buf); */ jsubscription_globalfailure(jua, je); } else if (je->type==EXOSIP_SUBSCRIPTION_NOTIFY) { /* snprintf(buf, 99, "<- (%i %i) NOTIFY from: %s", je->sid, je->did, je->remote_uri); josua_printf(buf); snprintf(buf, 99, "<- (%i %i) online=%i [status: %i reason:%i]", je->sid, je->did, je->online_status, je->ss_status, je->ss_reason); josua_printf(buf); */ jsubscription_notify(jua, je); } else if (je->type==EXOSIP_IN_SUBSCRIPTION_NEW) { /* snprintf(buf, 99, "<- (%i %i) SUBSCRIBE from: %s", je->nid, je->did, je->remote_uri); josua_printf(buf); */ /* search for the user to see if he has been previously accepted or not! */ eXosip_notify(je->did, EXOSIP_SUBCRSTATE_PENDING, EXOSIP_NOTIFY_AWAY); jinsubscription_new(jua, je); } else if (je->textinfo[0]!='\0') { /* snprintf(buf, 99, "(%i %i %i %i) %s", je->cid, je->sid, je->nid, je->did, je->textinfo); josua_printf(buf); */ } eXosip_event_free(je); } return(counter); }