From 16f584ef47561942d0623ab3511a495f0545581f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 18 Sep 2007 17:31:36 +0000 Subject: [PATCH] add register-gateway variable to directory users to allow inbound reg to trigger an outbound one git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5710 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/endpoints/mod_sofia/mod_sofia.c | 32 +++++++- src/mod/endpoints/mod_sofia/mod_sofia.h | 3 +- src/mod/endpoints/mod_sofia/sofia.c | 2 +- src/mod/endpoints/mod_sofia/sofia_reg.c | 103 +++++++++++++++++++----- 4 files changed, 118 insertions(+), 22 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 9ed301190a..8e48726249 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -942,9 +942,11 @@ static const char *sofia_state_names[] = { "UNREGED", "TRYING", "REGISTER", "REGED", + "UNREGISTER", "FAILED", "EXPIRED", - "NOREG" }; + "NOREG", + NULL}; struct cb_helper { sofia_profile_t *profile; @@ -1169,6 +1171,34 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t } + if (!strcasecmp(argv[1], "unregister")) { + char *gname = argv[2]; + sofia_gateway_t *gateway_ptr; + + if (switch_strlen_zero(gname)) { + stream->write_function(stream, "No gateway name provided!\n"); + goto done; + } + + if (!strcasecmp(gname, "all")) { + for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) { + gateway_ptr->retry = 0; + gateway_ptr->state = REG_STATE_UNREGISTER; + } + stream->write_function(stream, "+OK\n"); + } else if ((gateway_ptr = sofia_reg_find_gateway(gname))) { + gateway_ptr->retry = 0; + gateway_ptr->state = REG_STATE_UNREGISTER; + stream->write_function(stream, "+OK\n"); + sofia_reg_release_gateway(gateway_ptr); + } else { + stream->write_function(stream, "Invalid gateway!\n"); + } + + goto done; + } + + if (!strcasecmp(argv[1], "stop") || !strcasecmp(argv[1], "restart")) { int rsec = 3; int diff = (int) (time(NULL) - profile->started); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 19d0ab5ae1..8b2178e1cf 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -174,6 +174,7 @@ typedef enum { REG_STATE_TRYING, REG_STATE_REGISTER, REG_STATE_REGED, + REG_STATE_UNREGISTER, REG_STATE_FAILED, REG_STATE_EXPIRED, REG_STATE_NOREG, @@ -432,7 +433,7 @@ void sofia_presence_cancel(void); switch_status_t config_sofia(int reload, char *profile_name); void sofia_reg_auth_challange(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_regtype_t regtype, const char *realm, int stale); auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t const *authorization, - const char *regstr, char *np, size_t nplen, char *ip, switch_event_t **v_event); + const char *regstr, char *np, size_t nplen, char *ip, switch_event_t **v_event, long exptime); void sofia_reg_handle_sip_r_challenge(int status, char const *phrase, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, switch_core_session_t *session, sip_t const *sip, tagi_t tags[]); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 52aefda9f4..325b813c14 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -87,7 +87,7 @@ void sofia_event_callback(nua_event_t event, char network_ip[80]; get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_addr); auth_res = sofia_reg_parse_auth(profile, authorization, - (char *) sip->sip_request->rq_method_name, tech_pvt->key, strlen(tech_pvt->key), network_ip, NULL); + (char *) sip->sip_request->rq_method_name, tech_pvt->key, strlen(tech_pvt->key), network_ip, NULL, 0); } if (auth_res != AUTH_OK) { diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 04bf711d40..7d05816daf 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -70,6 +70,16 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now) gateway_ptr->expires = now + gateway_ptr->freq; gateway_ptr->state = REG_STATE_REGED; break; + + case REG_STATE_UNREGISTER: + nua_unregister(gateway_ptr->nh, + SIPTAG_FROM_STR(gateway_ptr->register_from), + SIPTAG_CONTACT_STR(gateway_ptr->register_contact), + SIPTAG_EXPIRES_STR(gateway_ptr->expires_str), + NUTAG_REGISTRAR(gateway_ptr->register_proxy), + NUTAG_OUTBOUND("no-options-keepalive"), NUTAG_OUTBOUND("no-validate"), NUTAG_KEEPALIVE(0), TAG_NULL()); + gateway_ptr->state = REG_STATE_NOREG; + break; case REG_STATE_UNREGED: if ((gateway_ptr->nh = nua_handle(gateway_ptr->profile->nua, NULL, NUTAG_URL(gateway_ptr->register_proxy), @@ -322,6 +332,7 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han const char *rpid = "unknown"; const char *display = "\"user\""; char network_ip[80]; + char *register_gateway = NULL; int network_port; int cd = 0; @@ -390,25 +401,30 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han if (authorization) { char *v_contact_str; - if ((auth_res = sofia_reg_parse_auth(profile, authorization, sip->sip_request->rq_method_name, key, keylen, network_ip, v_event)) == AUTH_STALE) { + if ((auth_res = sofia_reg_parse_auth(profile, authorization, sip->sip_request->rq_method_name, key, keylen, network_ip, v_event, exptime)) + == AUTH_STALE) { stale = 1; } - if (v_event && *v_event && (v_contact_str = switch_event_get_header(*v_event, "force-contact"))) { - if (!strcasecmp(v_contact_str, "nat-connectile-dysfunction") || !strcasecmp(v_contact_str, "NDLB-connectile-dysfunction")) { - if (contact->m_url->url_params) { - snprintf(contact_str, sizeof(contact_str), "%s ", - display, contact->m_url->url_user, network_ip, network_port, contact->m_url->url_params); + if (v_event && *v_event) { + register_gateway = switch_event_get_header(*v_event, "register-gateway"); + + if ((v_contact_str = switch_event_get_header(*v_event, "force-contact"))) { + if (!strcasecmp(v_contact_str, "nat-connectile-dysfunction") || !strcasecmp(v_contact_str, "NDLB-connectile-dysfunction")) { + if (contact->m_url->url_params) { + snprintf(contact_str, sizeof(contact_str), "%s ", + display, contact->m_url->url_user, network_ip, network_port, contact->m_url->url_params); + } else { + snprintf(contact_str, sizeof(contact_str), "%s ", display, contact->m_url->url_user, network_ip, network_port); + } + cd = 1; } else { - snprintf(contact_str, sizeof(contact_str), "%s ", display, contact->m_url->url_user, network_ip, network_port); - } - cd = 1; - } else { - char *p; - switch_copy_string(contact_str, v_contact_str, sizeof(contact_str)); - for(p = contact_str; p && *p; p++) { - if (*p == '\'' || *p == '[' || *p == ']') { - *p = '"'; + char *p; + switch_copy_string(contact_str, v_contact_str, sizeof(contact_str)); + for(p = contact_str; p && *p; p++) { + if (*p == '\'' || *p == '[' || *p == ']') { + *p = '"'; + } } } } @@ -438,12 +454,11 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han if (regtype != REG_REGISTER) { return 0; } - + if (exptime) { if (!sofia_reg_find_reg_url(profile, to_user, to_host, buf, sizeof(buf))) { sql = switch_mprintf("insert into sip_registrations values ('%q','%q','%q','%q', '%q', %ld)", to_user, to_host, contact_str, cd ? "Registered(NATHACK)" : "Registered", rpid, (long) time(NULL) + (long) exptime * 2); - } else { sql = switch_mprintf @@ -716,7 +731,7 @@ void sofia_reg_handle_sip_r_challenge(int status, } auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t const *authorization, - const char *regstr, char *np, size_t nplen, char *ip, switch_event_t **v_event) + const char *regstr, char *np, size_t nplen, char *ip, switch_event_t **v_event, long exptime) { int indexnum; const char *cur; @@ -829,9 +844,59 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t co for (param = switch_xml_child(xparams, "variable"); param; param = param->next) { const char *var = switch_xml_attr_soft(param, "name"); const char *val = switch_xml_attr_soft(param, "value"); - + sofia_gateway_t *gateway_ptr = NULL; + if (!switch_strlen_zero(var) && !switch_strlen_zero(val)) { switch_event_add_header(*v_event, SWITCH_STACK_BOTTOM, var, "%s", val); + + if (!strcasecmp(var, "register-gateway")) { + if (!strcasecmp(val, "all")) { + switch_xml_t gateways_tag, gateway_tag; + if ((gateways_tag = switch_xml_child(user, "gateways"))) { + for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) { + char *name = (char *) switch_xml_attr_soft(gateway_tag, "name"); + if (switch_strlen_zero(name)) { + name = "anonymous"; + } + + if ((gateway_ptr = sofia_reg_find_gateway(name))) { + gateway_ptr->retry = 0; + if (exptime) { + gateway_ptr->state = REG_STATE_UNREGED; + } else { + gateway_ptr->state = REG_STATE_UNREGISTER; + } + sofia_reg_release_gateway(gateway_ptr); + } + + } + } + } else { + int x, argc; + char *mydata, *argv[50]; + + mydata = strdup(val); + assert(mydata != NULL); + + argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0]))); + + for (x = 0; x < argc; x++) { + if ((gateway_ptr = sofia_reg_find_gateway((char *)argv[x]))) { + gateway_ptr->retry = 0; + if (exptime) { + gateway_ptr->state = REG_STATE_UNREGED; + } else { + gateway_ptr->state = REG_STATE_UNREGISTER; + } + sofia_reg_release_gateway(gateway_ptr); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Gateway '%s' not found.\n", argv[x]); + } + } + + free(mydata); + } + } } } }