static pj_status_t handle_ip_change_on_acc()
{
    int i = 0;
    pj_status_t status = PJ_SUCCESS;
    pj_bool_t acc_done[PJSUA_MAX_ACC];

    PJSUA_LOCK();

    if (pjsua_var.acc_cnt == 0) {
	PJ_LOG(3, (THIS_FILE,
		   "No account is set, IP change handling will stop"));
	pjsua_acc_end_ip_change(NULL);
	PJSUA_UNLOCK();
	return status;
    }

    /* Reset ip_change_active flag. */
    for (; i < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
	pjsua_var.acc[i].ip_change_op = PJSUA_IP_CHANGE_OP_NULL;
	acc_done[i] = PJ_FALSE;
    }

    for (i = 0; i < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
	pj_bool_t shutdown_transport = PJ_FALSE;
	pjsip_regc_info regc_info;
	char acc_id[PJSUA_MAX_ACC * 4];
	pjsua_acc *acc = &pjsua_var.acc[i];
	pjsip_transport *transport = NULL;
	pjsua_acc_id shut_acc_ids[PJSUA_MAX_ACC];
	unsigned shut_acc_cnt = 0;

	if (!acc->valid || (acc_done[i]))
	    continue;

	if (acc->regc) {
	    int j = 0;
	    pj_status_t found_restart_tp_fail = PJ_FALSE;

	    pjsip_regc_get_info(acc->regc, &regc_info);

	    /* Check if transport restart listener succeed. */
	    for (; j < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++j) {
		if (pjsua_var.tpdata[j].data.ptr != NULL &&
		  pjsua_var.tpdata[j].restart_status != PJ_SUCCESS &&
		  pjsua_var.tpdata[j].type == regc_info.transport->key.type)
		{
		    if ((pjsua_var.tpdata[j].data.factory
					   == regc_info.transport->factory) ||
			(pjsua_var.tpdata[j].data.tp
					       == regc_info.transport))
		    {
			found_restart_tp_fail = PJ_TRUE;
			break;
		    }
		}
	    }

	    if (found_restart_tp_fail) {
		if (acc->ka_timer.id) {
		    pjsip_endpt_cancel_timer(pjsua_var.endpt, &acc->ka_timer);
		    acc->ka_timer.id = PJ_FALSE;

		    if (acc->ka_transport) {
			pjsip_transport_dec_ref(acc->ka_transport);
			acc->ka_transport = NULL;
		    }
		}
		pjsua_acc_end_ip_change(acc);
		continue;
	    }

	    if ((regc_info.transport) &&
		((regc_info.transport->flag & PJSIP_TRANSPORT_DATAGRAM) == 0))
	    {
		transport = regc_info.transport;
		shutdown_transport = acc->cfg.ip_change_cfg.shutdown_tp;
		shut_acc_ids[shut_acc_cnt++] = acc->index;
	    }
	} else if (acc->cfg.reg_uri.slen &&
		   acc->reg_last_code != PJSIP_SC_OK &&
		   acc->reg_last_code != PJSIP_SC_REQUEST_TIMEOUT &&
		   acc->reg_last_code != PJSIP_SC_INTERNAL_SERVER_ERROR &&
		   acc->reg_last_code != PJSIP_SC_BAD_GATEWAY &&
		   acc->reg_last_code != PJSIP_SC_SERVICE_UNAVAILABLE &&
		   acc->reg_last_code != PJSIP_SC_SERVER_TIMEOUT &&
		   acc->reg_last_code != PJSIP_SC_TEMPORARILY_UNAVAILABLE)
	{
	    PJ_LOG(3, (THIS_FILE, "Permanent registration failure, "
		       "IP change handling will stop for acc %d", acc->index));

	    pjsua_acc_end_ip_change(acc);
	    continue;
	}
	pj_ansi_snprintf(acc_id, sizeof(acc_id), "#%d", i);

	if (transport) {
	    unsigned j = i + 1;

	    /* Find other account that uses the same transport. */
	    for (; j < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++j) {
		pjsip_regc_info tmp_regc_info;
		pjsua_acc *next_acc = &pjsua_var.acc[j];

		if (!next_acc->valid || !next_acc->regc ||
		    (next_acc->ip_change_op > PJSUA_IP_CHANGE_OP_NULL))
		{
		    continue;
		}

		pjsip_regc_get_info(next_acc->regc, &tmp_regc_info);
		if (transport == tmp_regc_info.transport) {
                    char tmp_buf[4];

                    pj_ansi_snprintf(tmp_buf, sizeof(tmp_buf), " #%d", j);
                    if (pj_ansi_strlen(acc_id) + pj_ansi_strlen(tmp_buf) <
                        sizeof(acc_id))
                    {
                        pj_ansi_strcat(acc_id, tmp_buf);
                    }

		    shut_acc_ids[shut_acc_cnt++] = j;
		    if (!shutdown_transport) {
			shutdown_transport =
				    next_acc->cfg.ip_change_cfg.shutdown_tp;
		    }
		}
	    }
	}

	if (shutdown_transport) {
	    unsigned j;
	    /* Shutdown the transport. */
	    PJ_LOG(3, (THIS_FILE, "Shutdown transport %s used by account %s "
		       "triggered by IP change", transport->obj_name, acc_id));

	    for (j = 0; j < shut_acc_cnt; ++j) {
		pjsua_acc *tmp_acc = &pjsua_var.acc[shut_acc_ids[j]];
		tmp_acc->ip_change_op = PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP;
		acc_done[shut_acc_ids[j]] = PJ_TRUE;
	    }

	    status = pjsip_transport_shutdown2(transport, PJ_TRUE);
	} else {
	    acc_done[i] = PJ_TRUE;
	    if (acc->cfg.allow_contact_rewrite && acc->cfg.reg_uri.slen) {
		status = pjsua_acc_update_contact_on_ip_change(acc);
	    } else {
		status = pjsua_acc_handle_call_on_ip_change(acc);
	    }
	}
    }
    PJSUA_UNLOCK();
    return status;
}