2
0
Эх сурвалжийг харах

modules/ims_qos: new mod param delete_contact_on_rx_failure
New param to decide whether to delete a contact if the associated Rx signalling session
is torn down

Richard Good 9 жил өмнө
parent
commit
40d3454ba6

+ 246 - 236
modules/ims_qos/cdpeventprocessor.c

@@ -64,262 +64,272 @@ extern int cdp_event_list_size_threshold;
 extern struct ims_qos_counters_h ims_qos_cnts_h;
 
 extern int terminate_dialog_on_rx_failure;
-
-int init_cdp_cb_event_list() {
-    cdp_event_list = shm_malloc(sizeof (cdp_cb_event_list_t));
-    if (!cdp_event_list) {
-        LM_ERR("No more SHM mem\n");
-        return 0;
-    }
-    memset(cdp_event_list, 0, sizeof (cdp_cb_event_list_t));
-    cdp_event_list->lock = lock_alloc();
-    if (!cdp_event_list->lock) {
-        LM_ERR("failed to create cdp event list lock\n");
-        return 0;
-    }
-    cdp_event_list->lock = lock_init(cdp_event_list->lock);
-    cdp_event_list->size = 0;
-
-    sem_new(cdp_event_list->empty, 0); //pre-locked - as we assume list is empty at start
-
-    return 1;
+extern int delete_contact_on_rx_failure;
+
+int init_cdp_cb_event_list()
+{
+		cdp_event_list = shm_malloc(sizeof(cdp_cb_event_list_t));
+		if (!cdp_event_list) {
+				LM_ERR("No more SHM mem\n");
+				return 0;
+		}
+		memset(cdp_event_list, 0, sizeof(cdp_cb_event_list_t));
+		cdp_event_list->lock = lock_alloc();
+		if (!cdp_event_list->lock) {
+				LM_ERR("failed to create cdp event list lock\n");
+				return 0;
+		}
+		cdp_event_list->lock = lock_init(cdp_event_list->lock);
+		cdp_event_list->size = 0;
+
+		sem_new(cdp_event_list->empty, 0); //pre-locked - as we assume list is empty at start
+
+		return 1;
 }
 
-void destroy_cdp_cb_event_list() {
-    cdp_cb_event_t *ev, *tmp;
-
-    lock_get(cdp_event_list->lock);
-    ev = cdp_event_list->head;
-    while (ev) {
-        tmp = ev->next;
-        free_cdp_cb_event(ev);
-        ev = tmp;
-    }
-    lock_destroy(cdp_event_list->lock);
-    lock_dealloc(cdp_event_list->lock);
-    shm_free(cdp_event_list);
+void destroy_cdp_cb_event_list()
+{
+		cdp_cb_event_t *ev, *tmp;
+
+		lock_get(cdp_event_list->lock);
+		ev = cdp_event_list->head;
+		while (ev) {
+				tmp = ev->next;
+				free_cdp_cb_event(ev);
+				ev = tmp;
+		}
+		lock_destroy(cdp_event_list->lock);
+		lock_dealloc(cdp_event_list->lock);
+		shm_free(cdp_event_list);
 }
 
-cdp_cb_event_t* new_cdp_cb_event(int event, str *rx_session_id, rx_authsessiondata_t *session_data) {
-    cdp_cb_event_t *new_event = shm_malloc(sizeof (cdp_cb_event_t));
-    if (!new_event) {
-        LM_ERR("no more shm mem\n");
-        return NULL;
-    }
-    memset(new_event, 0, sizeof (cdp_cb_event_t));
-
-    //we have to make a copy of the rx session id because it is not in shm mem
-    if ((rx_session_id->len > 0) && rx_session_id->s) {
-        LM_DBG("Creating new event for rx session [%.*s]\n", rx_session_id->len, rx_session_id->s);
-        new_event->rx_session_id.s = (char*) shm_malloc(rx_session_id->len);
-        if (!new_event->rx_session_id.s) {
-            LM_ERR("no more shm memory\n");
-            shm_free(new_event);
-            return NULL;
-        }
-        memcpy(new_event->rx_session_id.s, rx_session_id->s, rx_session_id->len);
-        new_event->rx_session_id.len = rx_session_id->len;
-    }
-
-    new_event->event = event;
-    new_event->registered = time(NULL);
-    new_event->session_data = session_data; //session_data is already in shm mem
-
-    return new_event;
+cdp_cb_event_t* new_cdp_cb_event(int event, str *rx_session_id, rx_authsessiondata_t *session_data)
+{
+		cdp_cb_event_t *new_event = shm_malloc(sizeof(cdp_cb_event_t));
+		if (!new_event) {
+				LM_ERR("no more shm mem\n");
+				return NULL;
+		}
+		memset(new_event, 0, sizeof(cdp_cb_event_t));
+
+		//we have to make a copy of the rx session id because it is not in shm mem
+		if ((rx_session_id->len > 0) && rx_session_id->s) {
+				LM_DBG("Creating new event for rx session [%.*s]\n", rx_session_id->len, rx_session_id->s);
+				new_event->rx_session_id.s = (char*) shm_malloc(rx_session_id->len);
+				if (!new_event->rx_session_id.s) {
+						LM_ERR("no more shm memory\n");
+						shm_free(new_event);
+						return NULL;
+				}
+				memcpy(new_event->rx_session_id.s, rx_session_id->s, rx_session_id->len);
+				new_event->rx_session_id.len = rx_session_id->len;
+		}
+
+		new_event->event = event;
+		new_event->registered = time(NULL);
+		new_event->session_data = session_data; //session_data is already in shm mem
+
+		return new_event;
 }
 //add to tail
 
-void push_cdp_cb_event(cdp_cb_event_t* event) {
-    lock_get(cdp_event_list->lock);
-    if (cdp_event_list->head == 0) { //empty list
-        cdp_event_list->head = cdp_event_list->tail = event;
-    } else {
-        cdp_event_list->tail->next = event;
-        cdp_event_list->tail = event;
-    }
-    cdp_event_list->size++;
-    if(cdp_event_list_size_threshold > 0 && cdp_event_list->size > cdp_event_list_size_threshold) {
-	    LM_WARN("cdp_event_list is size [%d] and has exceed cdp_event_list_size_threshold of [%d]", cdp_event_list->size, cdp_event_list_size_threshold);
-    }
-    sem_release(cdp_event_list->empty);
-    lock_release(cdp_event_list->lock);
+void push_cdp_cb_event(cdp_cb_event_t* event)
+{
+		lock_get(cdp_event_list->lock);
+		if (cdp_event_list->head == 0) { //empty list
+				cdp_event_list->head = cdp_event_list->tail = event;
+		} else {
+				cdp_event_list->tail->next = event;
+				cdp_event_list->tail = event;
+		}
+		cdp_event_list->size++;
+		if (cdp_event_list_size_threshold > 0 && cdp_event_list->size > cdp_event_list_size_threshold) {
+				LM_WARN("cdp_event_list is size [%d] and has exceed cdp_event_list_size_threshold of [%d]", cdp_event_list->size, cdp_event_list_size_threshold);
+		}
+		sem_release(cdp_event_list->empty);
+		lock_release(cdp_event_list->lock);
 }
 
 //pop from head
 
-cdp_cb_event_t* pop_cdp_cb_event() {
-    cdp_cb_event_t *ev;
+cdp_cb_event_t* pop_cdp_cb_event()
+{
+		cdp_cb_event_t *ev;
 
-    lock_get(cdp_event_list->lock);
-    while (cdp_event_list->head == 0) {
-        lock_release(cdp_event_list->lock);
-        sem_get(cdp_event_list->empty);
-        lock_get(cdp_event_list->lock);
-    }
+		lock_get(cdp_event_list->lock);
+		while (cdp_event_list->head == 0) {
+				lock_release(cdp_event_list->lock);
+				sem_get(cdp_event_list->empty);
+				lock_get(cdp_event_list->lock);
+		}
 
-    ev = cdp_event_list->head;
-    cdp_event_list->head = ev->next;
+		ev = cdp_event_list->head;
+		cdp_event_list->head = ev->next;
 
-    if (ev == cdp_event_list->tail) { //list now empty
-        cdp_event_list->tail = 0;
-    }
-    ev->next = 0; //make sure whoever gets this cant access our list
-    cdp_event_list->size--;
-    lock_release(cdp_event_list->lock);
+		if (ev == cdp_event_list->tail) { //list now empty
+				cdp_event_list->tail = 0;
+		}
+		ev->next = 0; //make sure whoever gets this cant access our list
+		cdp_event_list->size--;
+		lock_release(cdp_event_list->lock);
 
-    return ev;
+		return ev;
 }
 
 /*main event process function*/
-void cdp_cb_event_process() {
-    cdp_cb_event_t *ev;
-    udomain_t* domain;
-    pcontact_t* pcontact;
-    pcontact_info_t contact_info;
-
-    struct pcontact_info ci;
-    memset(&ci, 0, sizeof (struct pcontact_info));
-
-    for (;;) {
-        ev = pop_cdp_cb_event();
-
-        if (cdp_event_latency) { //track delays
-            unsigned int diff = time(NULL) - ev->registered;
-            if (diff > cdp_event_threshold) {
-                switch (cdp_event_latency_loglevel) {
-                    case 0:
-                        LM_ERR("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
-                        break;
-                    case 1:
-                        LM_WARN("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
-                        break;
-                    case 2:
-                        LM_INFO("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
-                        break;
-                    case 3:
-                        LM_DBG("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
-                        break;
-                    default:
-                        LM_DBG("Unknown log level....printing as debug\n");
-                        LM_DBG("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
-                        break;
-                }
-            }
-        }
-        LM_DBG("processing event [%d]\n", ev->event);
-        rx_authsessiondata_t *p_session_data = ev->session_data;
-        str *rx_session_id = &ev->rx_session_id;
-
-        switch (ev->event) {
-            case AUTH_EV_SESSION_TIMEOUT:
-            case AUTH_EV_SESSION_GRACE_TIMEOUT:
-            case AUTH_EV_RECV_ASR:
-                LM_DBG("Received notification of ASR from transport plane or CDP timeout for CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
-                        " and domain [%.*s]\n",
-                        rx_session_id->len, rx_session_id->s,
-                        p_session_data->registration_aor.len, p_session_data->registration_aor.s,
-                        p_session_data->domain.len, p_session_data->domain.s);
-
-
-                if (p_session_data->subscribed_to_signaling_path_status) {
-                    LM_DBG("This is a subscription to signalling bearer session");
-                    //nothing to do here - just wait for AUTH_EV_SERVICE_TERMINATED event
-                } else {
-                    LM_DBG("This is a media bearer session session");
-                    //this is a media bearer session that was terminated from the transport plane - we need to terminate the associated dialog
-                    //so we set p_session_data->must_terminate_dialog to 1 and when we receive AUTH_EV_SERVICE_TERMINATED event we will terminate the dialog
-                    //we only terminate the dialog if terminate_dialog_on_rx_failure is set
-                    if(terminate_dialog_on_rx_failure) {
-                        p_session_data->must_terminate_dialog = 1;
-                    }
-                }
-                break;
-
-            case AUTH_EV_SERVICE_TERMINATED:
-                LM_DBG("Received notification of CDP TERMINATE of CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
-                        " and domain [%.*s]\n",
-                        rx_session_id->len, rx_session_id->s,
-                        p_session_data->registration_aor.len, p_session_data->registration_aor.s,
-                        p_session_data->domain.len, p_session_data->domain.s);
-
-                if (p_session_data->subscribed_to_signaling_path_status) {
-                    LM_DBG("This is a subscription to signalling bearer session");
-                    //instead of removing the contact from usrloc_pcscf we just change the state of the contact to TERMINATE_PENDING_NOTIFY
-                    //pcscf_registrar sees this, sends a SIP PUBLISH and on SIP NOTIFY the contact is deleted
-		    //note we only send SIP PUBLISH if the session has been successfully opened
-		    
-		    if(p_session_data->session_has_been_opened) {
-			if (ul.register_udomain(p_session_data->domain.s, &domain)
-				< 0) {
-			    LM_DBG("Unable to register usrloc domain....aborting\n");
-			    return;
-			}
-			ul.lock_udomain(domain, &p_session_data->via_host, p_session_data->via_port, p_session_data->via_proto);
-                        
-                        contact_info.received_host = p_session_data->ip;
-                        contact_info.received_port = p_session_data->recv_port;
-                        contact_info.received_proto = p_session_data->recv_proto;
-                        contact_info.searchflag = (1 << SEARCH_RECEIVED);
-                        
-                        contact_info.via_host = p_session_data->via_host;
-                        contact_info.via_port = p_session_data->via_port;
-                        contact_info.via_prot = p_session_data->via_proto;
-                        contact_info.aor = p_session_data->registration_aor;
-						contact_info.reg_state = PCONTACT_ANY;
-                        
-			if (ul.get_pcontact(domain, &contact_info, &pcontact) != 0) {
-			    LM_DBG("no contact found for terminated Rx reg session..... ignoring\n");
-			} else {
-			    LM_DBG("Updating contact [%.*s] after Rx reg session terminated, setting state to PCONTACT_DEREG_PENDING_PUBLISH\n", pcontact->aor.len, pcontact->aor.s);
-			    ci.reg_state = PCONTACT_DEREG_PENDING_PUBLISH;
-			    ci.num_service_routes = 0;
-			    ul.update_pcontact(domain, &ci, pcontact);
-			}
-			ul.unlock_udomain(domain, &p_session_data->via_host, p_session_data->via_port, p_session_data->via_proto);
-			counter_add(ims_qos_cnts_h.active_registration_rx_sessions, -1);
-		    }
-                } else {
-                    LM_DBG("This is a media bearer session session");
-		    if(p_session_data->session_has_been_opened) {
-			LM_DBG("Session was opened so decrementing active_media_rx_sessions\n");
-			counter_add(ims_qos_cnts_h.active_media_rx_sessions, -1);
-		    }
-		    
-                    //we only terminate the dialog if this was triggered from the transport plane or timeout - i.e. if must_terminate_dialog is set
-                    //if this was triggered from the signalling plane (i.e. someone hanging up) then we don'y need to terminate the dialog
-                    if (p_session_data->must_terminate_dialog) {
-                        LM_DBG("Terminating dialog with callid, ftag, ttag: [%.*s], [%.*s], [%.*s]\n",
-                                p_session_data->callid.len, p_session_data->callid.s,
-                                p_session_data->ftag.len, p_session_data->ftag.s,
-                                p_session_data->ttag.len, p_session_data->ttag.s);
-                        dlgb.terminate_dlg(&p_session_data->callid,
-                                &p_session_data->ftag, &p_session_data->ttag, &confirmed_qosrelease_headers,
-                                &early_qosrelease_reason);
-                    }
-                }
-
-                //free callback data
-                if (p_session_data) {
-		    free_callsessiondata(p_session_data);
-                }
-                break;
-            default:
-                break;
-        }
-
-        free_cdp_cb_event(ev);
-    }
+void cdp_cb_event_process()
+{
+		cdp_cb_event_t *ev;
+		udomain_t* domain;
+		pcontact_t* pcontact;
+		pcontact_info_t contact_info;
+
+		struct pcontact_info ci;
+		memset(&ci, 0, sizeof(struct pcontact_info));
+
+		for (;;) {
+				ev = pop_cdp_cb_event();
+
+				if (cdp_event_latency) { //track delays
+						unsigned int diff = time(NULL) - ev->registered;
+						if (diff > cdp_event_threshold) {
+								switch (cdp_event_latency_loglevel) {
+								case 0:
+										LM_ERR("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
+										break;
+								case 1:
+										LM_WARN("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
+										break;
+								case 2:
+										LM_INFO("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
+										break;
+								case 3:
+										LM_DBG("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
+										break;
+								default:
+										LM_DBG("Unknown log level....printing as debug\n");
+										LM_DBG("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold);
+										break;
+								}
+						}
+				}
+				LM_DBG("processing event [%d]\n", ev->event);
+				rx_authsessiondata_t *p_session_data = ev->session_data;
+				str *rx_session_id = &ev->rx_session_id;
+
+				switch (ev->event) {
+				case AUTH_EV_SESSION_TIMEOUT:
+				case AUTH_EV_SESSION_GRACE_TIMEOUT:
+				case AUTH_EV_RECV_ASR:
+						LM_DBG("Received notification of ASR from transport plane or CDP timeout for CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
+								" and domain [%.*s]\n",
+								rx_session_id->len, rx_session_id->s,
+								p_session_data->registration_aor.len, p_session_data->registration_aor.s,
+								p_session_data->domain.len, p_session_data->domain.s);
+
+
+						if (p_session_data->subscribed_to_signaling_path_status) {
+								LM_DBG("This is a subscription to signalling bearer session");
+								//nothing to do here - just wait for AUTH_EV_SERVICE_TERMINATED event
+						} else {
+								LM_DBG("This is a media bearer session session");
+								//this is a media bearer session that was terminated from the transport plane - we need to terminate the associated dialog
+								//so we set p_session_data->must_terminate_dialog to 1 and when we receive AUTH_EV_SERVICE_TERMINATED event we will terminate the dialog
+								//we only terminate the dialog if terminate_dialog_on_rx_failure is set
+								if (terminate_dialog_on_rx_failure) {
+										p_session_data->must_terminate_dialog = 1;
+								}
+						}
+						break;
+
+				case AUTH_EV_SERVICE_TERMINATED:
+						LM_DBG("Received notification of CDP TERMINATE of CDP session with Rx session ID: [%.*s] and associated contact [%.*s]"
+								" and domain [%.*s]\n",
+								rx_session_id->len, rx_session_id->s,
+								p_session_data->registration_aor.len, p_session_data->registration_aor.s,
+								p_session_data->domain.len, p_session_data->domain.s);
+
+						if (p_session_data->subscribed_to_signaling_path_status) {
+								LM_DBG("This is a subscription to signalling bearer session");
+								//instead of removing the contact from usrloc_pcscf we just change the state of the contact to TERMINATE_PENDING_NOTIFY
+								//pcscf_registrar sees this, sends a SIP PUBLISH and on SIP NOTIFY the contact is deleted
+								//note we only send SIP PUBLISH if the session has been successfully opened
+
+								if (p_session_data->session_has_been_opened) {
+										if (delete_contact_on_rx_failure) {
+												if (ul.register_udomain(p_session_data->domain.s, &domain)
+														< 0) {
+														LM_DBG("Unable to register usrloc domain....aborting\n");
+														return;
+												}
+												ul.lock_udomain(domain, &p_session_data->via_host, p_session_data->via_port, p_session_data->via_proto);
+
+												contact_info.received_host = p_session_data->ip;
+												contact_info.received_port = p_session_data->recv_port;
+												contact_info.received_proto = p_session_data->recv_proto;
+												contact_info.searchflag = (1 << SEARCH_RECEIVED);
+
+												contact_info.via_host = p_session_data->via_host;
+												contact_info.via_port = p_session_data->via_port;
+												contact_info.via_prot = p_session_data->via_proto;
+												contact_info.aor = p_session_data->registration_aor;
+												contact_info.reg_state = PCONTACT_ANY;
+
+												if (ul.get_pcontact(domain, &contact_info, &pcontact) != 0) {
+														LM_DBG("no contact found for terminated Rx reg session..... ignoring\n");
+												} else {
+														LM_DBG("Updating contact [%.*s] after Rx reg session terminated, setting state to PCONTACT_DEREG_PENDING_PUBLISH\n", pcontact->aor.len, pcontact->aor.s);
+														ci.reg_state = PCONTACT_DEREG_PENDING_PUBLISH;
+														ci.num_service_routes = 0;
+														ul.update_pcontact(domain, &ci, pcontact);
+												}
+												ul.unlock_udomain(domain, &p_session_data->via_host, p_session_data->via_port, p_session_data->via_proto);
+										}
+										counter_add(ims_qos_cnts_h.active_registration_rx_sessions, -1);
+								}
+						} else {
+								LM_DBG("This is a media bearer session session");
+								if (p_session_data->session_has_been_opened) {
+										LM_DBG("Session was opened so decrementing active_media_rx_sessions\n");
+										counter_add(ims_qos_cnts_h.active_media_rx_sessions, -1);
+								}
+
+								//we only terminate the dialog if this was triggered from the transport plane or timeout - i.e. if must_terminate_dialog is set
+								//if this was triggered from the signalling plane (i.e. someone hanging up) then we don'y need to terminate the dialog
+								if (p_session_data->must_terminate_dialog) {
+										LM_DBG("Terminating dialog with callid, ftag, ttag: [%.*s], [%.*s], [%.*s]\n",
+												p_session_data->callid.len, p_session_data->callid.s,
+												p_session_data->ftag.len, p_session_data->ftag.s,
+												p_session_data->ttag.len, p_session_data->ttag.s);
+										dlgb.terminate_dlg(&p_session_data->callid,
+												&p_session_data->ftag, &p_session_data->ttag, &confirmed_qosrelease_headers,
+												&early_qosrelease_reason);
+								}
+						}
+
+						//free callback data
+						if (p_session_data) {
+								free_callsessiondata(p_session_data);
+						}
+						break;
+				default:
+						break;
+				}
+
+				free_cdp_cb_event(ev);
+		}
 }
 
-void free_cdp_cb_event(cdp_cb_event_t *ev) {
-    if (ev) {
-        LM_DBG("Freeing cdpb CB event structure\n");
-        if (ev->rx_session_id.len > 0 && ev->rx_session_id.s) {
-            LM_DBG("about to free string from cdp CB event [%.*s]\n", ev->rx_session_id.len, ev->rx_session_id.s);
-            shm_free(ev->rx_session_id.s);
-        }
-        shm_free(ev);
-    }
+void free_cdp_cb_event(cdp_cb_event_t *ev)
+{
+		if (ev) {
+				LM_DBG("Freeing cdpb CB event structure\n");
+				if (ev->rx_session_id.len > 0 && ev->rx_session_id.s) {
+						LM_DBG("about to free string from cdp CB event [%.*s]\n", ev->rx_session_id.len, ev->rx_session_id.s);
+						shm_free(ev->rx_session_id.s);
+				}
+				shm_free(ev);
+		}
 }
 
 

+ 41 - 23
modules/ims_qos/doc/ims_qos_admin.xml

@@ -121,29 +121,6 @@ modparam("ims_qos", "rx_auth_expiry", 14400)
       </example>
     </section>
 
-    <section>
-      <title><varname>af_signaling_ip</varname> (string)</title>
-
-      <para>Defines the IP address to use in the flow description for the
-      media flow of the SIP registration. This is known in EPC as the 
-      AF-Signaling path and usually would create a dedicated bearer for the SIP
-      signaling between the UE IP and the P-CSCF IP. 
-      
-      Usually set this value to the IP address of the P-CSCF.</para>
-
-      <para><emphasis> Default value is 127.0.0.1 - dummy value. </emphasis></para>
-
-      <example>
-        <title><varname>rx_auth_expiry</varname> parameter usage</title>
-
-        <programlisting format="linespecific">
-...
-modparam("ims_qos", "af_signaling_ip", "192.168.1.45")
-...
-        </programlisting>
-      </example>
-    </section>
-    
     <section>
       <title><varname>cdp_event_latency</varname> (integer)</title>
 
@@ -347,6 +324,47 @@ modparam("ims_qos", "regex_sdp_ip_prefix_to_maintain_in_fd", "10.21.0.1")
         </programlisting>
       </example>
     </section>
+    
+    <section>
+      <title><varname>terminate_dialog_on_rx_failure</varname> integer</title>
+
+      <para>If set then active dialogs associated with an Rx session are
+      torn down in the Rx session fails</para>
+
+      <para><emphasis> Default value is 1, dialogs are torn down</emphasis></para>
+
+      <example>
+        <title><varname>terminate_dialog_on_rx_failure</varname> parameter
+        usage</title>
+
+        <programlisting format="linespecific">
+...
+modparam("ims_qos", "terminate_dialog_on_rx_failure", 0)
+...
+        </programlisting>
+      </example>
+    </section>
+    
+    <section>
+      <title><varname>delete_contact_on_rx_failure</varname> integer</title>
+
+      <para>If set then contacts associated with signalling Rx sessions are deleted
+if the Rx session fails</para>
+
+      <para><emphasis> Default value is 1, contacts are deleted</emphasis></para>
+
+      <example>
+        <title><varname>delete_contact_on_rx_failure</varname> parameter
+        usage</title>
+
+        <programlisting format="linespecific">
+...
+modparam("ims_qos", "delete_contact_on_rx_failure", 0)
+...
+        </programlisting>
+      </example>
+    </section>
+    
   </section>
 
   <section>

+ 28 - 29
modules/ims_qos/mod.c

@@ -3,23 +3,23 @@
  *
  * Copyright (C) 2012 Smile Communications, [email protected]
  * Copyright (C) 2012 Smile Communications, [email protected]
- *
+ * 
  * The initial version of this code was written by Dragos Vingarzan
  * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
  * Fruanhofer Institute. It was and still is maintained in a separate
  * branch of the original SER. We are therefore migrating it to
  * Kamailio/SR and look forward to maintaining it from here on out.
  * 2011/2012 Smile Communications, Pty. Ltd.
- * ported/maintained/improved by
+ * ported/maintained/improved by 
  * Jason Penton (jason(dot)penton(at)smilecoms.com and
- * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
  * effort to add full IMS support to Kamailio/SR using a new and
  * improved architecture
- *
+ * 
  * NB: Alot of this code was originally part of OpenIMSCore,
- * FhG Fokus.
+ * FhG Fokus. 
  * Copyright (C) 2004-2006 FhG Fokus
- * Thanks for great work! This is an effort to
+ * Thanks for great work! This is an effort to 
  * break apart the various CSCF functions into logically separate
  * components. We hope this will drive wider use. We also feel
  * that in this way the architecture is more complete and thereby easier
@@ -37,10 +37,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
+ * 
  */
 
 #include <stdio.h>
@@ -126,17 +126,18 @@ static int fixup_aar(void** param, int param_no);
 int * callback_singleton; /*< Callback singleton */
 
 int terminate_dialog_on_rx_failure = 1; //this specifies whether a dialog is torn down when a media rx session fails - in some cases you might not want the dialog torn down
+int delete_contact_on_rx_failure = 1;  //If this is set we delete the contact if the associated signalling bearer is removed
+
 
 str early_qosrelease_reason = {"QoS released", 12};
 str confirmed_qosrelease_headers = {NULL, 0};
 
+
 /* parameters storage */
 str rx_dest_realm = str_init("ims.smilecoms.com");
 /* Only used if we want to force the Rx peer usually this is configured at a stack level and the first request uses realm routing */
 str rx_forced_peer = str_init("");
 
-/* P-CSCF IP address to generate the flows for the UE<->PCSCF signaling path */
-str af_signaling_ip = str_init("127.0.0.1");
 
 /* commands wrappers and fixups */
 static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *id, int id_type);
@@ -187,7 +188,6 @@ static param_export_t params[] = {
 		{ "rx_dest_realm", PARAM_STR, &rx_dest_realm},
 		{ "rx_forced_peer", PARAM_STR, &rx_forced_peer},
 		{ "rx_auth_expiry", INT_PARAM, &rx_auth_expiry},
-		{ "af_signaling_ip", PARAM_STR, &af_signaling_ip}, /* IP of this P-CSCF, to be used in the flow for the AF-signaling */
 		{ "cdp_event_latency", INT_PARAM, &cdp_event_latency}, /*flag: report slow processing of CDP callback events or not */
 		{ "cdp_event_threshold", INT_PARAM, &cdp_event_threshold}, /*time in ms above which we should report slow processing of CDP callback event*/
 		{ "cdp_event_latency_log", INT_PARAM, &cdp_event_latency_loglevel}, /*log-level to use to report slow processing of CDP callback event*/
@@ -198,6 +198,7 @@ static param_export_t params[] = {
 		{ "early_qosrelease_reason", PARAM_STR, &early_qosrelease_reason},
 		{ "confirmed_qosrelease_headers", PARAM_STR, &confirmed_qosrelease_headers},
 		{ "terminate_dialog_on_rx_failure", INT_PARAM, &terminate_dialog_on_rx_failure},
+		{ "delete_contact_on_rx_failure", INT_PARAM, &delete_contact_on_rx_failure},
 		{ "regex_sdp_ip_prefix_to_maintain_in_fd", PARAM_STR, &regex_sdp_ip_prefix_to_maintain_in_fd},
 		{ 0, 0, 0}
 };
@@ -720,8 +721,8 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int
 
 
 		/*  we may need the request message from here on.. if there are headers we need that were not parsed in the original request
-			(which we cannot assume) then we would pollute the shm_msg t->uas.request if we did any parsing on it. Instead, we need to
-			make a private copy of the message and free it when we are done
+			(which we cannot assume) then we would pollute the shm_msg t->uas.request if we did any parsing on it. Instead, we need to 
+			make a private copy of the message and free it when we are done 
 		 */
 		if ((_pv_treq.T != t || t->uas.request != _pv_treq.tmsgp)
 				&& t->uas.request->id != _pv_treq.id) {
@@ -947,7 +948,7 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int
 								identifier_type = AVP_Subscription_Id_Type_SIP_URI; //default is END_USER_SIP_URI
 						}
 				}
-				//IP
+				//IP 
 				//if its mo we use request SDP
 				//if its mt we use reply SDP
 				if (dlg_direction == DLG_MOBILE_ORIGINATING) {
@@ -965,9 +966,9 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int
 						}
 						ip = sdp_session->ip_addr;
 						ip_version = sdp_session->pf;
-
+						
 						LM_DBG("IP retrieved from Request SDP to use for framed IP address: [%.*s]", ip.len, ip.s);
-
+						
 						if (ip.len <= 0) {
 								LM_DBG("Request SDP connection IP could not be retrieved, so we use SDP stream IP");
 								sdp_stream = get_sdp_stream(orig_sip_request_msg, 0, 0);
@@ -975,7 +976,7 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int
 										LM_ERR("Missing SDP stream information from request\n");
 										goto error;
 								}
-
+								
 								ip = sdp_stream->ip_addr;
 								if (ip.len <= 0) {
 										LM_ERR("Request SDP IP information could not be retrieved");
@@ -986,11 +987,11 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int
 										LM_ERR("check_ip_version returned 0 \n");
 										goto error;
 								}
-
+								
 						}
-
+						
 						free_sdp((sdp_info_t**) (void*) &t->uas.request->body);
-
+						
 				} else {
 						LM_DBG("terminating direction\n");
 						//get ip from reply sdp (we use first SDP session)
@@ -1006,9 +1007,9 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int
 						}
 						ip = sdp_session->ip_addr;
 						ip_version = sdp_session->pf;
-
+						
 						LM_DBG("IP retrieved from Reply SDP to use for framed IP address: [%.*s]", ip.len, ip.s);
-
+						
 						if (ip.len <= 0) {
 								LM_DBG("Reply SDP connection IP could not be retrieved, so we use SDP stream IP");
 								sdp_stream = get_sdp_stream(msg, 0, 0);
@@ -1016,7 +1017,7 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int
 										LM_ERR("Missing SDP stream information from reply\n");
 										goto error;
 								}
-
+								
 								ip = sdp_stream->ip_addr;
 								if (ip.len <= 0) {
 										LM_ERR("Reply SDP IP information could not be retrieved");
@@ -1027,9 +1028,9 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int
 										LM_ERR("check_ip_version returned 0 \n");
 										goto error;
 								}
-
+								
 						}
-
+						
 						free_sdp((sdp_info_t**) (void*) &msg->body);
 				}
 
@@ -1059,7 +1060,6 @@ static int w_rx_aar(struct sip_msg *msg, char *route, char* dir, char *c_id, int
 						dlgb.set_dlg_var(&callid, &ftag, &ttag,
 								&term_session_key, &auth_session->id);
 				}
-				auth_session->vendor_id = IMS_vendor_id_3GPP;
 				LM_DBG("Attached CDP auth session [%.*s] for Rx to dialog in %s mode\n", auth_session->id.len, auth_session->id.s, direction);
 		} else {
 				LM_DBG("Update AAR session for this dialog in mode %s\n", direction);
@@ -1254,7 +1254,7 @@ static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char*
 				goto error;
 		}
 
-		//we use the received IP address for the framed_ip_address
+		//we use the received IP address for the framed_ip_address 
 		recv_ip.s = ip_addr2a(&msg->rcv.src_ip);
 		recv_ip.len = strlen(ip_addr2a(&msg->rcv.src_ip));
 
@@ -1338,7 +1338,6 @@ static int w_rx_aar_register(struct sip_msg *msg, char* route, char* str1, char*
 														goto error;
 												}
 												auth->u.auth.class = AUTH_CLASS_RXREG;
-												auth->vendor_id = IMS_vendor_id_3GPP;
 										}
 
 										//we are ready to send the AAR async. lets save the local data data