示例#1
0
static void
__dialog_cbtest(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
{
	str tag;

	LM_DBG("dialog callback received, from=%.*s, to=%.*s\n",
		dlg->from_uri.len, dlg->from_uri.s, dlg->to_uri.len, dlg->to_uri.s);

	if (dlg->tag[0].len && dlg->tag[0].s ) {
		LM_DBG("dialog callback: tag[0] = %.*s\n",
			dlg->tag[0].len, dlg->tag[0].s);
	}
	if (dlg->tag[0].len && dlg->tag[1].s ) {
		LM_DBG("dialog callback: tag[1] = %.*s\n",
			dlg->tag[1].len, dlg->tag[1].s);
	}

	if (_params->msg && _params->msg!=FAKED_REPLY && type != DLGCB_DESTROY) {
		/* get to tag*/
		if ( !_params->msg->to) {
			/* to header not defined, parse to header */
			LM_DBG("to header not defined, parse to header\n");
			if (parse_headers(_params->msg, HDR_TO_F,0)<0) {
				/* parser error */
				LM_ERR("parsing of to-header failed\n");
				tag.s = 0;
				tag.len = 0;
			} else if (!_params->msg->to) {
				/* to header still not defined */
				LM_ERR("no to although to-header is parsed: bad reply "
					"or missing TO hdr :-/\n");
				tag.s = 0;
				tag.len = 0;
			} else
				tag = get_to(_params->msg)->tag_value;
		} else {
			tag = get_to(_params->msg)->tag_value;
			if (tag.s==0 || tag.len==0) {
				LM_DBG("missing TAG param in TO hdr :-/\n");
				tag.s = 0;
				tag.len = 0;
			}
		}
		if (tag.s) {
			LM_DBG("dialog callback: _params->msg->to->parsed->tag_value "
				"= %.*s\n", tag.len, tag.s);
		}
	}

	switch (type) {
	case DLGCB_FAILED:
		LM_DBG("dialog callback type 'DLGCB_FAILED' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_CONFIRMED:
		LM_DBG("dialog callback type 'DLGCB_CONFIRMED' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_REQ_WITHIN:
		LM_DBG("dialog callback type 'DLGCB_REQ_WITHIN' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_TERMINATED:
		LM_DBG("dialog callback type 'DLGCB_TERMINATED' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_EXPIRED:
		LM_DBG("dialog callback type 'DLGCB_EXPIRED' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_EARLY:
		LM_DBG("dialog callback type 'DLGCB_EARLY' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_RESPONSE_FWDED:
		LM_DBG("dialog callback type 'DLGCB_RESPONSE_FWDED' received, "
			"from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_RESPONSE_WITHIN:
		LM_DBG("dialog callback type 'DLGCB_RESPONSE_WITHIN' received, "
			"from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_MI_CONTEXT:
		LM_DBG("dialog callback type 'DLGCB_MI_CONTEXT' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	case DLGCB_DESTROY:
		LM_DBG("dialog callback type 'DLGCB_DESTROY' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
		break;
	default:
		LM_DBG("dialog callback type 'unknown' received, from=%.*s\n",
			dlg->from_uri.len, dlg->from_uri.s);
	}
}
示例#2
0
int is_other_contact_f(struct sip_msg* msg, char* _d, char *_s)
{
	pv_spec_p spec = (pv_spec_p)_s;
	struct usr_avp *avp = NULL;
	urecord_t *r = NULL;
	str ip, contact;
	str uri, aor;
	ucontact_t *c;
	contact_t* ct;
	int exp, found;
	udomain_t* ud = (udomain_t*)_d;
	
	if (parse_message(msg) < 0) {
		LM_ERR("unable to parse message\n");
		return -2;
	}
	if (!ud) {
		LM_ERR("no location specified\n");
		return -2;
	}
	/* msg doesn't have contacts */
	if (!msg->contact ||
			!(ct = (((contact_body_t*)msg->contact->parsed)->contacts)))
		return -1;


	while (ct) {
		/* if expires is 0 */
		calc_contact_expires(msg, ct->expires, &exp);
		if (exp)
			break;
		ct = ct->next;
	}

	if (!ct) {
		LM_DBG("contact has expire 0\n");
		return -1;
	}

	uri = get_to(msg)->uri;
	if (extract_aor(&uri, &aor) < 0) {
		LM_ERR("failed to extract AOR record\n");
		return -2;
	}

	ul.lock_udomain(ud, &aor);
	ul.get_urecord(ud, &aor, &r);
	if (!r) {
		/* dont't test anything */
		LM_DBG("no contact found for aor=<%.*s>\n", aor.len, aor.s);
		found = -1;
		goto end;
	} else {
		c = r->contacts;
	}	

	while (c) {
		if (!c->received.len || !c->received.s || c->received.len < 4 /* sip:*/) {
			c = c->next;
			continue;
		}

		contact.s = c->received.s + 4;
		/* check for "sips:" */
		if (*contact.s == ':') {
			contact.len = c->received.len - 5;
			contact.s++;
		} else {
			/* skip "sip:" */
			contact.len = c->received.len - 4;
		}

		avp = NULL;
		found = 0;

		/* the ip should always be a string */
		while ((avp = search_first_avp(spec->pvp.pvn.u.isname.type,
						spec->pvp.pvn.u.isname.name.n, (int_str *)&ip, avp))!=0) {
			if (!(avp->flags & AVP_VAL_STR)) {
				LM_NOTICE("avp value should be string\n");
				continue;
			}
			if ((contact.len == ip.len || (contact.len>ip.len && contact.s[ip.len]==':'))
					&& !memcmp(contact.s, ip.s, ip.len)) {
				found = 1;
				break;
			}
		}

		if (!found) {
			LM_DBG("no contact <%.*s> registered earlier\n",
					contact.len, contact.s);
			found = 1;
			goto end;
		}

		c = c->next;
	}
	found = -1;

end:
	ul.unlock_udomain(ud, &aor);
	return found;
}
示例#3
0
/*Create cell to control Subscriber Dialog States
  This cell save this information:
  - Dialog Id:
  .Callid
  .rem_tag
  .local_tag
  - expires
  - Local_uri
  - Remote_uri
  - Notifier_uri
  - INVITE's Callid
  - Event body
  - State
  */
int create_subscriber_cell(struct sip_msg* reply, struct parms_cb* params_cb){

	str* callid = NULL;
	int expires= 0;
	struct to_body *pto= NULL, *pfrom = NULL;
	int size_subs_cell;
	int vsp_addr_len;
	char *vsp_addr = "@vsp.com";
	time_t rawtime;
	int time_now;
	struct sm_subscriber *subs_cell = NULL;
	char *p;
	unsigned int hash_code;

	callid= (str*) pkg_malloc (sizeof (str));
	if (callid == NULL) {
		LM_ERR("--------------------------------------------------no more pkg memory\n");
		return 0;
	}
	/*Verify repĺy is OK and get callid and expires from response*/
	if ( !extract_reply_headers(reply, callid, expires)){
		LM_ERR("fail in extract headers\n");
		pkg_free(callid);
		return 0;
	}

	/*get From header fields */
	pfrom = get_from(reply);
	LM_DBG("PFROM: %.*s \n ", pfrom->uri.len, pfrom->uri.s );
	if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0){
		LM_ERR("reply without tag value \n");
		pkg_free(callid);
		return 0;
	}

	/*get To header fields */
	pto = get_to(reply);
	LM_DBG("PTO: %.*s \n ", pto->uri.len, pto->uri.s );
	if (pto == NULL || pto->error != PARSE_OK) {
		LM_ERR("failed to parse TO header\n");
		pkg_free(callid);
		return 0;
	}

	// get source ip address that send INVITE
	vsp_addr = ip_addr2a(&reply->rcv.src_ip);
	vsp_addr_len = strlen(vsp_addr);

	time(&rawtime);
	time_now = (int)rawtime;
	LM_DBG("TIME : %d \n", (int)rawtime );

	/* build subscriber cell */
	size_subs_cell = sizeof (struct sm_subscriber) + (2 * sizeof(struct dialog_id))
		+ callid->len + pfrom->tag_value.len + pto->tag_value.len + pfrom->uri.len + pto->uri.len
		+ params_cb->callid_ori.len +  params_cb->event.len + params_cb->from_tag.len + vsp_addr_len + 9 ;
	subs_cell = pkg_malloc(size_subs_cell + 1);
	if (!subs_cell) {
		LM_ERR("no more shm\n");
		return 0;
	}

	memset(subs_cell, 0, size_subs_cell + 1);
	subs_cell->expires = expires;
	subs_cell->timeout =  TIMER_N + time_now;
	LM_DBG("SUBS_TIMEOUT: %d \n ", subs_cell->timeout );
	subs_cell->version =  -1;

	subs_cell->dlg_id = (struct dialog_id*)(subs_cell + 1);

	subs_cell->dlg_id->callid.len = callid->len;
	subs_cell->dlg_id->callid.s = (char *) (subs_cell->dlg_id + 1);
	memcpy(subs_cell->dlg_id->callid.s, callid->s, callid->len);
	LM_DBG("SUBS_CALLID: %.*s \n ", subs_cell->dlg_id->callid.len, subs_cell->dlg_id->callid.s );

	subs_cell->dlg_id->local_tag.len = pfrom->tag_value.len;
	subs_cell->dlg_id->local_tag.s = (char *) (subs_cell->dlg_id + 1) + callid->len;
	memcpy(subs_cell->dlg_id->local_tag.s, pfrom->tag_value.s, pfrom->tag_value.len);
	LM_DBG("SUBS_FROM_TAG: %.*s \n ", subs_cell->dlg_id->local_tag.len, subs_cell->dlg_id->local_tag.s );

	subs_cell->dlg_id->rem_tag.len = pto->tag_value.len;
	subs_cell->dlg_id->rem_tag.s = (char *) (subs_cell->dlg_id + 1) + callid->len + pfrom->tag_value.len;
	memcpy(subs_cell->dlg_id->rem_tag.s, pto->tag_value.s, pto->tag_value.len);
	LM_DBG("SUBS_TO_TAG: %.*s \n ", subs_cell->dlg_id->rem_tag.len, subs_cell->dlg_id->rem_tag.s );

	p = (char *)(subs_cell->dlg_id + 1) + callid->len + pfrom->tag_value.len + pto->tag_value.len;
	subs_cell->call_dlg_id = (struct dialog_id*)p;

	subs_cell->call_dlg_id->callid.len= params_cb->callid_ori.len;
	subs_cell->call_dlg_id->callid.s = (char *) (subs_cell->call_dlg_id + 1);
	memcpy(subs_cell->call_dlg_id->callid.s, params_cb->callid_ori.s, params_cb->callid_ori.len);
	LM_DBG("SUBS_CALLID_ORI: %.*s \n ", subs_cell->call_dlg_id->callid.len, subs_cell->call_dlg_id->callid.s );

	subs_cell->call_dlg_id->local_tag.len= params_cb->from_tag.len;
	subs_cell->call_dlg_id->local_tag.s = (char *) (subs_cell->call_dlg_id + 1) + params_cb->callid_ori.len;
	memcpy(subs_cell->call_dlg_id->local_tag.s, params_cb->from_tag.s, params_cb->from_tag.len);
	LM_DBG("SUBS_FROMTAG_event: %.*s \n ", subs_cell->call_dlg_id->local_tag.len, subs_cell->call_dlg_id->local_tag.s );

	subs_cell->loc_uri.len = pfrom->uri.len;
	subs_cell->loc_uri.s = (char *) (subs_cell->call_dlg_id + 1) + params_cb->callid_ori.len + params_cb->from_tag.len;
	memcpy(subs_cell->loc_uri.s,pfrom->uri.s,pfrom->uri.len);
	LM_DBG("SUBS_LOC_URI: %.*s \n ", subs_cell->loc_uri.len, subs_cell->loc_uri.s );

	subs_cell->rem_uri.len= pto->uri.len;
	subs_cell->rem_uri.s = (char *) (subs_cell->call_dlg_id + 1) + params_cb->callid_ori.len + params_cb->from_tag.len + pfrom->uri.len;
	memcpy(subs_cell->rem_uri.s, pto->uri.s, pto->uri.len);
	LM_DBG("SUBS_REM_URI: %.*s \n ", subs_cell->rem_uri.len, subs_cell->rem_uri.s );

	subs_cell->event.len= params_cb->event.len;
	subs_cell->event.s = (char *) (subs_cell->call_dlg_id + 1) + params_cb->callid_ori.len + params_cb->from_tag.len + pfrom->uri.len + pto->uri.len;
	memcpy(subs_cell->event.s, params_cb->event.s, params_cb->event.len);
	LM_DBG("SUBS_EVENT: %.*s \n ", subs_cell->event.len, subs_cell->event.s );

	subs_cell->contact.len = vsp_addr_len + 9;
	subs_cell->contact.s = (char *) (subs_cell->call_dlg_id + 1) + params_cb->callid_ori.len + params_cb->from_tag.len + pfrom->uri.len + pto->uri.len + params_cb->event.len;
	memcpy(subs_cell->contact.s, "sip:test@", 9);
	memcpy(subs_cell->contact.s + 9, vsp_addr, vsp_addr_len);
	LM_DBG("SUBS_CONTACT: %.*s \n ", subs_cell->contact.len, subs_cell->contact.s );

	subs_cell->dlg_id->status = NOTIFY_WAIT;

	hash_code= core_hash(&subs_cell->dlg_id->callid, 0, subst_size);
	LM_DBG("********************************************HASH_CODE%d\n", hash_code);


	if(insert_shtable(subs_htable, hash_code,subs_cell) == NULL){
		LM_ERR("inserting new record in subs_htable\n");
	}

	pkg_free(subs_cell);
	pkg_free(callid);

	return 1;

}
示例#4
0
/*!
 * \brief Function that is registered as TM callback and called on replies
 *
 * Function that is registered as TM callback and called on replies. It
 * parses the reply and set the appropriate event. This is then used to
 * update the dialog state, run eventual dialog callbacks and save or
 * update the necessary informations about the dialog.
 * \see next_state_dlg
 * \param t transaction, unused
 * \param type type of the entered callback
 * \param param saved dialog structure in the callback
 */
static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param) {
    struct dlg_cell *dlg;
    struct dlg_cell_out *dlg_out = 0;

    int new_state, old_state, unref, event;
    str to_tag, to_uri;
    struct sip_msg *req = param->req;
    struct sip_msg *rpl = param->rpl;
    struct dlg_entry_out* dlg_entry_out = 0;

    if (t && t->fwded_totags)
        LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i] and TO is [%.*s]\n", type, t->fwded_totags->tag.len, t->fwded_totags->tag.s);
    else
        LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i]\n", type);

    dlg = (struct dlg_cell *) (*param->param);
    if (shutdown_done || dlg == 0)
        return;

    if (t) {
        dlg->transaction = t;
    }

    LM_DBG("DLG dialogid is entry:id [%i:%i]\n", dlg->h_entry, dlg->h_id);

    if (type == TMCB_RESPONSE_FWDED) {
        // The state does not change, but the msg is mutable in this callback
        LM_DBG("TMCB_RESPONSE_FWDED from TM received");
        run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
        return;
    }

    if (type == TMCB_RESPONSE_OUT) {
        LM_DBG("TMCB_RESPONSE_OUT\n");
        return;
    }

    if (type == TMCB_RESPONSE_READY) {
        if (rpl == FAKED_REPLY) {
            LM_DBG("Faked reply\n");
            return;
        }

        // get to tag
        LM_DBG("Extracting to-tag from reply");
        if (!rpl->to && ((parse_headers(rpl, HDR_TO_F, 0) < 0) || !rpl->to)) {
            LM_ERR("bad reply or missing TO hdr :-/\n");
            to_tag.s = 0;
            to_tag.len = 0;
        } else {
            //populate to uri for this branch.
            to_uri = get_to(rpl)->uri;

            to_tag = get_to(rpl)->tag_value;
            if (to_tag.s == 0 || to_tag.len == 0) {
                LM_ERR("missing TAG param in TO hdr :-/\n");
                to_tag.s = 0;
                to_tag.len = 0;
                //Here we assume that the transaction module timer will remove any early dialogs
                return;
            }
        }

        LM_DBG("Got to-tag from response: %.*s \n", to_tag.len, to_tag.s);
    }

    if (type == TMCB_DESTROY)
        event = DLG_EVENT_TDEL;
    else if (param->code < 200)
        event = DLG_EVENT_RPL1xx;
    else if (param->code < 300)
        event = DLG_EVENT_RPL2xx;
    else
        event = DLG_EVENT_RPL3xx;

    LM_DBG("Calling next_state_dlg and event is %i\n", event);
    next_state_dlg(dlg, event, &old_state, &new_state, &unref, &to_tag);

    if (type == TMCB_RESPONSE_READY) {
        LM_DBG("Checking if there is an existing dialog_out entry with same to-tag");

        dlg_entry_out = &dlg->dlg_entry_out;

        lock_get(dlg->dlg_out_entries_lock);
        dlg_out = dlg_entry_out->first;

        LM_DBG("Scanning dlg_entry_out list for dlg_out");
        while (dlg_out) {
            //Check if there is an already dialog_out entry with same To-tag
            if (dlg_out->to_tag.len == to_tag.len &&
                    memcmp(dlg_out->to_tag.s, to_tag.s, dlg_out->to_tag.len) == 0) {
                //Found a dialog_out entry with same to_tag!
                LM_DBG("Found dlg_out for to-tag: %.*s\n", dlg_out->to_tag.len, dlg_out->to_tag.s);
                break;
            }
            dlg_out = dlg_out->next;
        }
        lock_release(dlg->dlg_out_entries_lock);

        if (!dlg_out) {
            LM_DBG("No dlg_out entry found - creating a new dialog_out entry on dialog [%p]\n", dlg);
            dlg_out = build_new_dlg_out(dlg, &to_uri, &to_tag);

            link_dlg_out(dlg, dlg_out, 0);

            /* save callee's cseq, caller cseq, callee contact and callee record route*/
            if (populate_leg_info(dlg, rpl, t, DLG_CALLEE_LEG, &to_tag) != 0) {
                LM_ERR("could not add further info to the dlg out\n");
            }

            if (!dlg_out) {
                LM_ERR("failed to create new dialog out structure\n");
                //TODO do something on this error!

            }
        } else {
            //This dlg_out already exists, update cseq and contact if present

            LM_DBG("dlg_out entry found - updating cseq's for dialog out [%p] for to-tag [%.*s] \n", dlg_out, dlg_out->to_tag.len, dlg_out->to_tag.s);

            if ((!rpl->cseq && parse_headers(rpl, HDR_CSEQ_F, 0) < 0) || !rpl->cseq ||
                    !rpl->cseq->parsed) {
                LM_ERR("bad sip message or missing CSeq hdr :-/\n");
            }
            dlg_update_cseq(dlg, DLG_CALLEE_LEG, &((get_cseq(rpl))->number), &(dlg_out->to_tag));


            /* extract the contact address to update if present*/
            if (!rpl->contact && (parse_headers(rpl, HDR_CONTACT_F, 0) < 0 || !rpl->contact)) {
                LM_ERR("Can not update callee contact: bad sip message or missing Contact hdr\n");
            }
            else if (parse_contact(rpl->contact) < 0 ||
                    ((contact_body_t *) rpl->contact->parsed)->contacts == NULL ||
                    ((contact_body_t *) rpl->contact->parsed)->contacts->next != NULL) {
                LM_ERR("Can not update callee contact: bad Contact HDR\n");
            }
            else
            {
                str contact;
                contact = ((contact_body_t *) rpl->contact->parsed)->contacts->uri;
                dlg_update_contact(dlg, DLG_CALLEE_LEG, &contact, &(dlg_out->to_tag));
            }

        }
    }

    if (new_state == DLG_STATE_EARLY) {
	if ((dlg->dflags & DLG_FLAG_INSERTED) == 0) {
	    dlg->dflags |= DLG_FLAG_NEW;
	} else {
	    dlg->dflags |= DLG_FLAG_CHANGED;
	}
	if (dlg_db_mode == DB_MODE_REALTIME)
	    update_dialog_dbinfo(dlg);

	run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
	return;
    }

    LM_DBG("new state is %i and old state is %i\n", new_state, old_state);

    if ((new_state == DLG_STATE_CONFIRMED) && (event == DLG_EVENT_RPL2xx)) {
        LM_DBG("dialog %p confirmed \n", dlg);
        //Remove all the other entries in dialog_out for the same dialog after TM expires the transaction
        //(not before in order to absorb late in-early-dialog requests).

        //remove all other dlg_out objects
        if (dlg_out) {
            if (d_tmb.register_tmcb(req, NULL, TMCB_DESTROY, unlink_dlgouts_from_cb, (void*) dlg, NULL) < 0) {
                LM_ERR("failed to register deletion delay function\n");
                LM_DBG("Removing all other DLGs");
                dlg_remove_dlg_out(dlg_out, dlg, 0);
            } else {
                //mark the outs for deletion
                dlg_remove_dlg_out(dlg_out, dlg, 1);

            }
        } else {
            LM_ERR("There is no dlg_out structure - this is bad\n");
            //TODO: add error handling here
        }

        /* set start time */
        dlg->start_ts = (unsigned int) (time(0));

        /* save the settings to the database,
         * if realtime saving mode configured- save dialog now
         * else: the next time the timer will fire the update*/
        if ((dlg->dflags & DLG_FLAG_INSERTED) == 0) {
	    dlg->dflags |= DLG_FLAG_NEW;
	} else {
	    dlg->dflags |= DLG_FLAG_CHANGED;
	}
	if (dlg_db_mode == DB_MODE_REALTIME)
		update_dialog_dbinfo(dlg);
	

        if (0 != insert_dlg_timer(&dlg->tl, dlg->lifetime)) {
            LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
                    "with clid '%.*s' and tags '%.*s' \n",
                    dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
                    dlg->callid.len, dlg->callid.s,
                    dlg->from_tag.len, dlg->from_tag.s);

        } else {
            ref_dlg(dlg, 1);
        }

        run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);

        if (unref) unref_dlg(dlg, unref);
        return;
    }

    if (new_state == DLG_STATE_CONCURRENTLY_CONFIRMED && (old_state == DLG_STATE_CONFIRMED || old_state == DLG_STATE_CONCURRENTLY_CONFIRMED)) {
        //This is a concurrently confirmed call
        LM_DBG("This is a concurrently confirmed call.");
        //Create a new Dialog ID token “X”
        //Not sure how to do this so just going to use existing Did and add an X character to it
        str new_did;
        create_concurrent_did(dlg, &new_did);

        //assign new did to the created or updated dialog_out entry.
        update_dlg_out_did(dlg_out, &new_did);

        //Then, duplicate the dialog_in entry and set its Dialog ID value to new_did
        //for now rather just create new dlg structure with the correct params - this should be fixed if future use requires

        struct dlg_cell *new_dlg = 0;
        new_dlg = build_new_dlg(&(dlg->callid) /*callid*/,
                &(dlg->from_uri) /*from uri*/,
                &(dlg->from_tag)/*from_tag*/,
                &(dlg->req_uri) /*r-uri*/);

        //assign new did to dlg_in
        update_dlg_did(new_dlg, &new_did);

        if (new_dlg == 0) {
            LM_ERR("failed to create new dialog\n");
            return;
        }

        //link the new_dlg with dlg_out object
        link_dlg_out(new_dlg, dlg_out, 0);

    }

    if (old_state != DLG_STATE_DELETED && new_state == DLG_STATE_DELETED) {
        LM_DBG("dialog %p failed (negative reply)\n", dlg);
        /* dialog setup not completed (3456XX) */
        run_dlg_callbacks(DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
        /* do unref */
        if (unref)
            unref_dlg(dlg, unref);

        return;
    }

    if (unref) unref_dlg(dlg, unref);

    return;
}
示例#5
0
/* builds digest string of msg
   Return value: 1: success
                 0: else
    digestString must point to an array with at least MAX_DIGEST bytes
*/
static int makeDigestString(char * digestString, char * dateHF,
														struct sip_msg * msg)
{
	struct to_body * from = NULL;
	struct to_body * to = NULL;
	struct cseq_body * cseq = NULL;
	struct hdr_field * date = NULL;
	contact_t * contact = NULL;
	unsigned int l;
	str tmp;

	if(!digestString || !msg)
	{
		LM_ERR("not all parameters set\n");
		return 0;
	}

	l = 0;

	/* ###from### */
	if(parse_from_header(msg) != 0)
	{
		LM_ERR("error parsing from header\n");
		return 0;
	}

	from = get_from(msg);
	if(!from)
	{
		LM_ERR("error getting from header\n");
		return 0;
	}

	if (l+from->uri.len+1>MAX_DIGEST) {
		LM_ERR("buffer to short 1\n");
		return 0;
	}
	memcpy( digestString+l, from->uri.s, from->uri.len);
	l += from->uri.len;
	*(digestString+(l++)) = '|';

	/* ###To### */
	to = get_to(msg);
	if(!to)
	{
		LM_ERR("error getting to header\n");
		return 0;
	}

	if (l+to->uri.len+1>MAX_DIGEST) {
		LM_ERR("buffer to short 2\n");
		return 0;
	}
	memcpy( digestString+l, to->uri.s, to->uri.len);
	l += to->uri.len;
	*(digestString+(l++)) = '|';

	/* ###callid### */
	if(!msg->callid)
	{
		LM_ERR("error getting callid header\n");
		return 0;
	}

	if (l+msg->callid->body.len+1>MAX_DIGEST) {
		LM_ERR("buffer to short 3\n");
		return 0;
	}
	memcpy( digestString+l, msg->callid->body.s, msg->callid->body.len);
	l += msg->callid->body.len;
	*(digestString+(l++)) = '|';

	/* ###CSeq### */
	cseq = (struct cseq_body *)msg->cseq->parsed;
	if (!cseq)
	{
		LM_ERR("error getting cseq header\n");
		return 0;
	}

	tmp.s = cseq->number.s;
	tmp.len = cseq->number.len;

	/* strip leading zeros */
	while((*(tmp.s) == '0') && (tmp.len > 1))
	{
		(tmp.s)++;
		(tmp.len)--;
	}

	if (l+tmp.len+cseq->method.len+2>MAX_DIGEST) {
		LM_ERR("buffer to short 4\n");
		return 0;
	}
	memcpy( digestString+l, tmp.s, tmp.len);
	l += tmp.len;
	*(digestString+(l++)) = ' ';
	memcpy( digestString+l, cseq->method.s, cseq->method.len);
	l += cseq->method.len;
	*(digestString+(l++)) = '|';

	/* ###Date### */
	if(!dateHF)
	{
		/* Date header field is taken from msg: verifier */
		date = get_header_by_static_name(msg,"Date");
		if (!date)
		{
			LM_ERR("error getting date header\n");
			return 0;
		}
		tmp = date->body;
	}
	else
	{
		/* Date header field is taken from dateHF: authentication service */
		tmp.s = dateHF;
		tmp.len = strlen(tmp.s);
	}

	if (l+tmp.len+1>MAX_DIGEST) {
		LM_ERR("buffer to short 5\n");
		return 0;
	}
	memcpy( digestString+l, tmp.s, tmp.len);
	l += tmp.len;
	*(digestString+(l++)) = '|';

	/* ###Contact### */
	if(msg->contact)
	{
		if(parse_contact(msg->contact) != 0)
		{
			LM_ERR("error parsing contact header\n");
			return 0;
		}
		/* first contact in list */
		contact = ((contact_body_t *)(msg->contact->parsed))->contacts;
		tmp = contact->uri;
	} else {
		tmp.len = 0;
		tmp.s = 0;
	}

	if (l+tmp.len+1>MAX_DIGEST) {
		LM_ERR("buffer to short 6\n");
		return 0;
	}
	if (tmp.len) {
		memcpy( digestString+l, tmp.s, tmp.len);
		l += tmp.len;
	}
	*(digestString+(l++)) = '|';

	/* ###body### */
	if ( get_body(msg,&tmp)!=0 ) {
		LM_ERR("failed to inspect body\n");
		return 0;
	}
	if (tmp.len != 0) {
		if (l+tmp.len+1>MAX_DIGEST) {
			LM_ERR("buffer to short 7\n");
			return 0;
		}
		memcpy( digestString+l, tmp.s, tmp.len);
		l += tmp.len;
		*(digestString+(l++)) = 0;
	}

	LM_DBG("Digest-String=>%s<\n", digestString);
	return 1;
}
示例#6
0
void subs_cback_func(struct cell *t, int cb_type, struct tmcb_params *ps)
{
	struct sip_msg* msg= NULL;
	int lexpire= 0;
	unsigned int cseq;
	ua_pres_t* presentity= NULL, *hentity= NULL;
	struct to_body *pto= NULL, *pfrom = NULL;
	int size= 0;
	int flag ;
	str record_route= {0, 0};
	int rt;
	str contact;
	int initial_request = 0;

	if(ps==NULL || ps->param== NULL || *ps->param== NULL )
	{
		LM_ERR("null callback parameter\n");
		return;
	}
	LM_DBG("completed with status %d\n",ps->code) ;
	hentity= (ua_pres_t*)(*ps->param);
	flag= hentity->flag;
	if(hentity->flag & XMPP_INITIAL_SUBS)
		hentity->flag= XMPP_SUBSCRIBE;

	/* get dialog information from reply message: callid, to_tag, from_tag */
	msg= ps->rpl;
	if(msg == NULL)
	{
		LM_ERR("no reply message found\n ");
		goto error;
	}

	if(msg== FAKED_REPLY)
	{
		/* delete record from hash_table and call registered functions */

		if(hentity->call_id.s== NULL) /* if a new requets failed-> do nothing*/
		{
			LM_DBG("initial Subscribe request failed\n");
			goto done;
		}
		lock_get(&HashT->p_records[hentity->hash_index].lock);
		presentity = get_htable_safe(hentity->hash_index, hentity->local_index);
		if(presentity)
		{
			delete_htable_safe(presentity, hentity->hash_index);
			lock_release(&HashT->p_records[hentity->hash_index].lock);
		}
		lock_release(&HashT->p_records[hentity->hash_index].lock);
		goto done;
	}

	if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
	{
		LM_ERR("when parsing headers\n");
		goto done;
	}

	/*if initial request */

	if(hentity->call_id.s== NULL)
	{
		initial_request = 1;
		if(ps->code>= 300)
		{
			LM_DBG("initial Subscribe request failed\n");
			goto done;
		}

		if( msg->callid==NULL || msg->callid->body.s==NULL)
		{
			LM_ERR("cannot parse callid header\n");
			goto done;
		}

		if (!msg->from || !msg->from->body.s)
		{
			LM_ERR("cannot find 'from' header!\n");
			goto done;
		}
		if (msg->from->parsed == NULL)
		{
			if ( parse_from_header( msg )<0 ) 
			{
				LM_ERR("cannot parse From header\n");
				goto done;
			}
		}
		pfrom = (struct to_body*)msg->from->parsed;

		if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
		{
			LM_ERR("no from tag value present\n");
			goto done;
		}
		if( msg->to==NULL || msg->to->body.s==NULL)
		{
			LM_ERR("cannot parse TO header\n");
			goto done;
		}

		pto = get_to(msg);
		if (pto == NULL || pto->error != PARSE_OK) {
			LM_ERR("failed to parse TO header\n");
			goto done;
		}

		if( pto->tag_value.s ==NULL || pto->tag_value.len == 0)
		{
			LM_ERR("no to tag value present\n");
			goto done;
		}
		hentity->call_id=  msg->callid->body;
		hentity->to_tag= pto->tag_value;
		hentity->from_tag= pfrom->tag_value;

	}

	/* extract the other necesary information for inserting a new record */
	if(ps->rpl->expires && msg->expires->body.len > 0)
	{
		if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
		{
			LM_ERR("cannot parse Expires header\n");
			goto done;
		}
		lexpire = ((exp_body_t*)msg->expires->parsed)->val;
		LM_DBG("lexpire= %d\n", lexpire);
	}

	if(ps->code >= 300 )
	{	/* if an error code and a stored dialog delete it and try to send 
		   a subscription with type= INSERT_TYPE, else return*/

		if(!initial_request)
		{
			subs_info_t subs;

			lock_get(&HashT->p_records[hentity->hash_index].lock);
			presentity = get_htable_safe(hentity->hash_index, hentity->local_index);
			if(presentity)
			{
				hentity->event= presentity->event;
				delete_htable_safe(presentity, hentity->hash_index);
				lock_release(&HashT->p_records[hentity->hash_index].lock);
			}
			lock_release(&HashT->p_records[hentity->hash_index].lock);

			memset(&subs, 0, sizeof(subs_info_t));
			subs.pres_uri= hentity->pres_uri;
			subs.to_uri  = hentity->to_uri;
			subs.watcher_uri= hentity->watcher_uri;
			subs.contact= &hentity->contact;

			if(hentity->remote_contact.s)
				subs.remote_target= &hentity->remote_contact;

			if(hentity->desired_expires== 0)
				subs.expires= -1;
			else
			if(hentity->desired_expires< (int)time(NULL))
				subs.expires= 0;
			else
				subs.expires= hentity->desired_expires- (int)time(NULL)+ 3;

			subs.flag= INSERT_TYPE;
			subs.source_flag= flag;
			subs.event= hentity->event;
			subs.id= hentity->id;
			subs.outbound_proxy= hentity->outbound_proxy;
			subs.extra_headers= &hentity->extra_headers;
			subs.cb_param= hentity->cb_param;

			if(send_subscribe(&subs)< 0)
			{
				LM_ERR("when trying to send SUBSCRIBE\n");
				goto done;
			}
		}
		goto done;
	}
	/*if a 2XX reply handle the two cases- an existing dialog and a new one*/

	/* extract the contact */
	if(msg->contact== NULL || msg->contact->body.s== NULL)
	{
		LM_ERR("no contact header found");
		goto error;
	}
	if( parse_contact(msg->contact) <0 )
	{
		LM_ERR(" cannot parse contact header\n");
		goto error;
	}

	if(msg->contact->parsed == NULL)
	{
		LM_ERR("cannot parse contact header\n");
		goto error;
	}
	contact = ((contact_body_t* )msg->contact->parsed)->contacts->uri;

	if(!initial_request)
	{
		/* do not delete the dialog - allow Notifies to be recognized as
		 * inside a known dialog */
	        if (lexpire == 0)
	                lexpire = 5;

		LM_DBG("*** Update expires\n");
		update_htable(hentity->hash_index, hentity->local_index, lexpire, NULL, &contact);
		goto done;
	}

	/* if a new dialog -> insert */
	if(lexpire== 0)
	{
		LM_DBG("expires= 0: no not insert\n");
		goto done;
	}

	if( msg->cseq==NULL || msg->cseq->body.s==NULL)
	{
		LM_ERR("cannot parse cseq header\n");
		goto done;
	}

	if( str2int( &(get_cseq(msg)->number), &cseq)< 0)
	{
		LM_ERR("while converting str to int\n");
		goto done;
    }

	/*process record route and add it to a string*/
	if (msg->record_route!=NULL)
	{
		rt = print_rr_body(msg->record_route, &record_route, 1, 0);
		if(rt != 0)
		{
			LM_ERR("parsing record route [%d]\n", rt);
			record_route.s=NULL;
			record_route.len=0;
		}
	}

	size= sizeof(ua_pres_t)+ 2*sizeof(str)+(hentity->pres_uri->len+ pto->uri.len+
		pfrom->uri.len+ pto->tag_value.len+ pfrom->tag_value.len
		+msg->callid->body.len+ record_route.len+ hentity->contact.len+
		hentity->id.len )*sizeof(char);

	presentity= (ua_pres_t*)shm_malloc(size);
	if(presentity== NULL)
	{
		LM_ERR("no more share memory\n");
		if(record_route.s)
			pkg_free(record_route.s);
		goto done;
	}
	memset(presentity, 0, size);
	size= sizeof(ua_pres_t);

	presentity->pres_uri= (str*)( (char*)presentity+ size);
	size+= sizeof(str);
	presentity->pres_uri->s= (char*)presentity+ size;
	memcpy(presentity->pres_uri->s, hentity->pres_uri->s, hentity->pres_uri->len);
	presentity->pres_uri->len= hentity->pres_uri->len;
	size+= hentity->pres_uri->len;

	presentity->to_uri.s= (char*)presentity+ size;
	memcpy(presentity->to_uri.s, pto->uri.s, pto->uri.len);
	presentity->to_uri.len= pto->uri.len;
	size+= pto->uri.len;

	presentity->watcher_uri= (str*)( (char*)presentity+ size);
	size+= sizeof(str);
	presentity->watcher_uri->s= (char*)presentity+ size;
	memcpy(presentity->watcher_uri->s, pfrom->uri.s, pfrom->uri.len);
	presentity->watcher_uri->len= pfrom->uri.len;
	size+= pfrom->uri.len;

	presentity->call_id.s= (char*)presentity + size;
	memcpy(presentity->call_id.s,msg->callid->body.s, 
		msg->callid->body.len);
	presentity->call_id.len= msg->callid->body.len;
	size+= presentity->call_id.len;

	presentity->to_tag.s= (char*)presentity + size;
	memcpy(presentity->to_tag.s,pto->tag_value.s, 
			pto->tag_value.len);
	presentity->to_tag.len= pto->tag_value.len;
	size+= pto->tag_value.len;

	presentity->from_tag.s= (char*)presentity + size;
	memcpy(presentity->from_tag.s,pfrom->tag_value.s, 
			pfrom->tag_value.len);
	presentity->from_tag.len= pfrom->tag_value.len;
	size+= pfrom->tag_value.len;

	if(record_route.len && record_route.s)
	{
		presentity->record_route.s= (char*)presentity + size;
		memcpy(presentity->record_route.s, record_route.s, record_route.len);
		presentity->record_route.len= record_route.len;
		size+= record_route.len;
		pkg_free(record_route.s);
	}


	presentity->contact.s= (char*)presentity + size;
	memcpy(presentity->contact.s, hentity->contact.s, hentity->contact.len);
	presentity->contact.len= hentity->contact.len;
	size+= hentity->contact.len;

	if(hentity->id.s)
	{
		presentity->id.s=(char*)presentity+ size;
		memcpy(presentity->id.s, hentity->id.s, 
			hentity->id.len);
		presentity->id.len= hentity->id.len; 
		size+= presentity->id.len;
	}

	if(hentity->extra_headers.s && hentity->extra_headers.len)
	{
		presentity->extra_headers.s= (char*)shm_malloc(hentity->extra_headers.len* sizeof(char));
		if(presentity->extra_headers.s== NULL)
		{
			ERR_MEM(SHARE_MEM);
		}
		memcpy(presentity->extra_headers.s, hentity->extra_headers.s, hentity->extra_headers.len);
		presentity->extra_headers.len= hentity->extra_headers.len;
	}

	/* write the remote contact filed */
	presentity->remote_contact.s= (char*)shm_malloc(contact.len* sizeof(char));
	if(presentity->remote_contact.s== NULL)
	{
		ERR_MEM(SHARE_MEM);
	}
	memcpy(presentity->remote_contact.s, contact.s, contact.len);
	presentity->remote_contact.len= contact.len;

	presentity->event|= hentity->event;
	presentity->flag= hentity->flag;
	presentity->etag.s= NULL;
	presentity->cseq= cseq;
	presentity->desired_expires= hentity->desired_expires;
	presentity->expires= lexpire+ (int)time(NULL);
	if(BLA_SUBSCRIBE & presentity->flag)
	{
		LM_DBG("BLA_SUBSCRIBE FLAG inserted\n");
	}
	LM_DBG("record for subscribe from %.*s to %.*s inserted in datatbase\n",
			presentity->watcher_uri->len, presentity->watcher_uri->s,
			presentity->pres_uri->len, presentity->pres_uri->s);
	insert_htable(presentity);

done:
	if(hentity->ua_flag == REQ_OTHER)
	{
		hentity->flag= flag;
		run_pua_callbacks( hentity, msg);
	}
error:
	if(hentity)
	{
	        if(presentity)
	        {
		        if(presentity->extra_headers.s)
		                shm_free(presentity->extra_headers.s);
		        if(presentity->remote_contact.s)
		                shm_free(presentity->remote_contact.s);
	        }
		shm_free(hentity);
		hentity= NULL;
	}
	return;
}
示例#7
0
int run_helper_logic(struct sip_msg *msg, void *param)
{
	str totag;
	str status_404 = str_init("Not Here");
	str status_500 = str_init("Server Internal Error");
	int rc, seq_request = 0;

	LM_DBG("running helper logic\n");

	if (parse_headers(msg, HDR_TO_F|HDR_CALLID_F, 0) == -1) {
		LM_ERR("failed to parse To header\n");
		return SCB_DROP_MSG;
	}

	totag = get_to(msg)->tag_value;

	/* sequential request */
	if (totag.s && totag.len > 0) {
		seq_request = 1;

		if (msg->REQ_METHOD == METHOD_INVITE)
			rr_api.record_route(msg, NULL);

		/* if not RR_DRIVEN */
		if (rr_api.loose_route(msg) < 0) {

			/* attempt a full dialog search (not the usual quick did lookup) */
			if (use_dialog && dlg_api.match_dialog(msg) < 0)
				LM_ERR("failed to match dialog, ci '%.*s'\n",
				       msg->callid->body.len, msg->callid->body.s);

			if (msg->REQ_METHOD == METHOD_ACK) {
				rc = tm_api.t_check_trans(msg, NULL, NULL, NULL, NULL, NULL, NULL);
				if (rc > 0)
					tm_api.t_relay(msg, NULL, NULL, NULL, NULL, NULL, NULL);

				return SCB_RUN_POST_CBS;
			}

			sl_api.reply(msg, 404, &status_404);
			return SCB_RUN_POST_CBS;
		}
	}

	if (msg->REQ_METHOD == METHOD_CANCEL) {
		seq_request = 1;

		rc = tm_api.t_check_trans(msg, NULL, NULL, NULL, NULL, NULL, NULL);
		if (rc > 0)
			tm_api.t_relay(msg, NULL, NULL, NULL, NULL, NULL, NULL);

		return SCB_RUN_POST_CBS;
	}

	if (tm_api.t_check_trans(msg, NULL, NULL, NULL, NULL, NULL, NULL) == 0)
		return SCB_RUN_POST_CBS;

	/**
	 * for sequential requests:
	 * - optionally run a given route
	 * - relay them and do not trigger the request route at all
	 */
	if (seq_request) {
		if (seq_route_id > 0) {
			LM_DBG("running seq route '%s'\n", seq_route);
			if (run_top_route(rlist[seq_route_id].a, msg) & ACT_FL_DROP) {
				LM_DBG("script exited in the seq route\n");

				return SCB_RUN_POST_CBS;
			}
		}

		if (tm_api.t_relay(msg, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
			sl_api.reply(msg, 500, &status_500);

		return SCB_RUN_POST_CBS;
	}

	/* record-routing for initial requests */
	if (!(msg->REQ_METHOD & (METHOD_REGISTER|METHOD_MESSAGE)))
		rr_api.record_route(msg, NULL);

	if (use_dialog && msg->REQ_METHOD & METHOD_INVITE)
		dlg_api.create_dlg(msg, create_dialog_flags);

	return SCB_RUN_ALL;
}
示例#8
0
/* get data from Subscriber and save in list link with notify information:
   . dialog id of emergency call
   . dialog id of subscribe
   . local uri
   . remote uri
   . contact
   . expires
   . time to expire subscriber
   - status
   . cell next
   . cell previus
   */
struct sm_subscriber* build_notify_cell(struct sip_msg *msg, int expires){

	char *subs_callid, *subs_fromtag;
	str callid_event;
	str fromtag_event;
	str callid;
	struct to_body *pto= NULL, *pfrom = NULL;
	int size_notify_cell;
	int vsp_addr_len;
	char *vsp_addr = "@vsp.com";
	int vsp_port = 5060;
	int size_vsp_port = 4;
	char* str_vsp_port;
	struct sm_subscriber *notify_cell = NULL;
	time_t rawtime;
	int time_now;
	char *p;
	unsigned int hash_code;
	static str msg489={"Bad Event",sizeof("Bad Event")-1};


	// get data from SUBSCRIBE request
	// get callid from Subscribe
	if( msg->callid==NULL || msg->callid->body.s==NULL){
		LM_ERR("subscribe without callid header\n");
		return NULL;
	}
	callid = msg->callid->body;
	LM_DBG("CALLID: %.*s \n ", callid.len, callid.s );

	//get From header from Subscribe
	if (msg->from->parsed == NULL){
		if ( parse_from_header( msg )<0 ){
			LM_ERR("subscribe without From header\n");
			return NULL;
		}
	}
	pfrom = get_from(msg);
	LM_DBG("PFROM: %.*s \n ", pfrom->uri.len, pfrom->uri.s );
	LM_DBG("PFROM_TAG: %.*s \n ", pfrom->tag_value.len, pfrom->tag_value.s );
	if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0){
		LM_ERR("subscribe without from_tag value \n");
		return NULL;
	}
	if( msg->to==NULL || msg->to->body.s==NULL){
		LM_ERR("error in parse TO header\n");
		return NULL;
	}

	// get To header from Subscribe
	pto = get_to(msg);
	if (pto == NULL || pto->error != PARSE_OK) {
		LM_ERR("failed to parse TO header\n");
		return NULL;
	}

	LM_DBG("PTO: %.*s \n ", pto->uri.len, pto->uri.s );
	LM_DBG("PTO_TAG: %.*s \n ", pto->tag_value.len, pto->tag_value.s );

	/* get in event header: callid and from_tag */
	if(get_event_header(msg, &subs_callid, &subs_fromtag) != 1){
		LM_ERR("failed to parse Event header\n");
		return NULL;
	}

	LM_DBG("SUBS_CALLID: %s\n ", subs_callid);
	LM_DBG("SUBS_FROMTAG: %s\n ", subs_fromtag);
	callid_event.s = subs_callid;
	callid_event.len = strlen(subs_callid);
	fromtag_event.s = subs_fromtag;
	fromtag_event.len = strlen(subs_fromtag);

	hash_code= core_hash(&callid_event, 0, emet_size);
	LM_DBG("********************************************HASH_CODE%d\n", hash_code);

	// search call hash with hash_code, callidHeader and from/to_tag params
	if (search_ehtable(call_htable, subs_callid, subs_fromtag, hash_code, 0) == NULL) {
		LM_ERR(" ---CALLID NOT FOUND IN SHTABLE\n");
		if(!eme_tm.t_reply(msg,489,&msg489)){
			LM_DBG("t_reply (489)\n");
		}
		pkg_free(callid_event.s);
		pkg_free(fromtag_event.s);
		return 0;
	}
	LM_DBG("CALLID OK in subs_hash\n");

	time(&rawtime);
	time_now = (int)rawtime;
	LM_DBG("TIME : %d \n", (int)rawtime );

	// get source ip address that send INVITE
	vsp_addr = ip_addr2a(&msg->rcv.src_ip);
	vsp_addr_len = strlen(vsp_addr);
	vsp_port = msg->rcv.src_port;
	str_vsp_port= int2str(vsp_port, &size_vsp_port);
	LM_DBG("SRC_PORT : %s \n", str_vsp_port);

	/* build notifier cell */
	size_notify_cell = sizeof(struct sm_subscriber) + (2 * sizeof(struct dialog_id))
		+ callid.len + pfrom->tag_value.len + pto->tag_value.len + pfrom->uri.len + pto->uri.len
		+ callid_event.len +  fromtag_event.len + vsp_addr_len + size_vsp_port + 11  ;
	notify_cell = pkg_malloc(size_notify_cell + 1);
	if (!notify_cell) {
		LM_ERR("no more shm\n");
		return NULL;
	}

	memset(notify_cell, 0, size_notify_cell + 1);
	notify_cell->expires = expires;
	LM_DBG("EXPIRES: %d \n ", notify_cell->expires );
	notify_cell->timeout =  TIMER_N + time_now;
	LM_DBG("SUBS_TIMEOUT: %d \n ", notify_cell->timeout );
	notify_cell->version =  0;
	LM_DBG("SUBS_VERSION: %d \n ", notify_cell->version );

	notify_cell->dlg_id = (struct dialog_id*)(notify_cell + 1);

	notify_cell->dlg_id->callid.len = callid.len;
	notify_cell->dlg_id->callid.s = (char *) (notify_cell->dlg_id + 1);
	memcpy(notify_cell->dlg_id->callid.s, callid.s, callid.len);
	LM_DBG("SUBS_CALLID: %.*s \n ", notify_cell->dlg_id->callid.len, notify_cell->dlg_id->callid.s );

	notify_cell->dlg_id->rem_tag.len = pfrom->tag_value.len;
	notify_cell->dlg_id->rem_tag.s = (char *) (notify_cell->dlg_id + 1) + callid.len;
	memcpy(notify_cell->dlg_id->rem_tag.s, pfrom->tag_value.s, pfrom->tag_value.len);
	LM_DBG("SUBS_FROM_TAG: %.*s \n ", notify_cell->dlg_id->rem_tag.len, notify_cell->dlg_id->rem_tag.s );

	p = (char *)(notify_cell->dlg_id + 1) + callid.len + pfrom->tag_value.len;
	notify_cell->call_dlg_id = (struct dialog_id*)p;

	notify_cell->call_dlg_id->callid.len= callid_event.len;
	notify_cell->call_dlg_id->callid.s = (char *) (notify_cell->call_dlg_id + 1);
	memcpy(notify_cell->call_dlg_id->callid.s, callid_event.s, callid_event.len);
	LM_DBG("SUBS_CALLID_event: %.*s \n ", notify_cell->call_dlg_id->callid.len, notify_cell->call_dlg_id->callid.s );

	notify_cell->call_dlg_id->rem_tag.len= fromtag_event.len;
	notify_cell->call_dlg_id->rem_tag.s = (char *) (notify_cell->call_dlg_id + 1) + callid_event.len;
	memcpy(notify_cell->call_dlg_id->rem_tag.s, fromtag_event.s, fromtag_event.len);
	LM_DBG("SUBS_FROMTAG_event: %.*s \n ", notify_cell->call_dlg_id->rem_tag.len, notify_cell->call_dlg_id->rem_tag.s );

	notify_cell->loc_uri.len = pto->uri.len;
	notify_cell->loc_uri.s = (char *) (notify_cell->call_dlg_id + 1) + callid_event.len + fromtag_event.len;
	memcpy(notify_cell->loc_uri.s,pto->uri.s,pto->uri.len);
	LM_DBG("SUBS_LOC_URI: %.*s \n ", notify_cell->loc_uri.len, notify_cell->loc_uri.s );

	notify_cell->rem_uri.len= pfrom->uri.len;
	notify_cell->rem_uri.s = (char *) (notify_cell->call_dlg_id + 1) + callid_event.len + fromtag_event.len + pto->uri.len;
	memcpy(notify_cell->rem_uri.s, pfrom->uri.s, pfrom->uri.len);
	LM_DBG("SUBS_REM_URI: %.*s \n ", notify_cell->rem_uri.len, notify_cell->rem_uri.s );

	notify_cell->contact.len = vsp_addr_len + size_vsp_port +11;
	notify_cell->contact.s = (char *) (notify_cell->call_dlg_id + 1) +  pfrom->uri.len + pto->uri.len + callid_event.len + fromtag_event.len;

	memcpy(notify_cell->contact.s, "sip:teste@", 10);
	memcpy(notify_cell->contact.s + 10, vsp_addr, vsp_addr_len);
	memcpy(notify_cell->contact.s + 10 + vsp_addr_len, ":", 1);
	memcpy(notify_cell->contact.s + 11 + vsp_addr_len, str_vsp_port, size_vsp_port);
	LM_DBG("SUBS_CONTACT: %.*s \n ", notify_cell->contact.len, notify_cell->contact.s );

	notify_cell->dlg_id->status =  RESP_WAIT;

	pkg_free(callid_event.s);
	pkg_free(fromtag_event.s);

	return notify_cell;

}
示例#9
0
int push_on_network(struct sip_msg *msg, int net)
{
	str    body;
	struct sip_uri  uri;
	struct sms_msg  *sms_messg;
	struct to_body  *from;
	char   *p;
	int    len;
	int    mime;

	/* get the message's body
	 * anyhow we have to call this function, so let's do it at the beginning
	 * to force the parsing of all the headers - like this we avoid separate
	 * calls of parse_headers function for FROM, CONTENT_LENGTH, TO hdrs  */
	body.s = get_body( msg );
	if (body.s==0) {
		LM_ERR("failed to extract body from msg!\n");
		goto error;
	}

	/* content-length (if present) must be already parsed */
	if (!msg->content_length) {
		LM_ERR("no Content-Length header found!\n");
		goto error;
	}
	body.len = get_content_length( msg );

	/* parse the content-type header */
	if ( (mime=parse_content_type_hdr(msg))<1 ) {
		LM_ERR("failed to parse Content-Type header\n");
		goto error;
	}

	/* check the content-type value */
	if ( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN
	&& mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM ) {
		LM_ERR("invalid content-type for a message request! type found=%d\n",
				mime);
		goto error;
	}

	/* we try to get the user name (phone number) first from the RURI 
	   (in our case means from new_uri or from first_line.u.request.uri);
	   if it's missing there (like in requests generated by MSN MESSENGER),
	   we go for "to" header
	*/
	LM_DBG("string to get user from new_uri\n");
	if ( !msg->new_uri.s||parse_uri( msg->new_uri.s,msg->new_uri.len,&uri)
	|| !uri.user.len )
	{
		LM_DBG("string to get user from R_uri\n");
		if ( parse_uri( msg->first_line.u.request.uri.s,
		msg->first_line.u.request.uri.len ,&uri)||!uri.user.len )
		{
			LM_DBG("string to get user from To\n");
			if ( (!msg->to&&((parse_headers(msg,HDR_TO_F,0)==-1) ||
					!msg->to)) ||
				parse_uri( get_to(msg)->uri.s, get_to(msg)->uri.len, &uri)==-1
			|| !uri.user.len)
			{
				LM_ERR("unable to extract user name from RURI and To header!\n");
				goto error;
			}
		}
	}
	/* check the uri.user format = '+(inter code)(number)' */
	if (uri.user.len<2 || uri.user.s[0]!='+' || uri.user.s[1]<'1'
	|| uri.user.s[1]>'9') {
		LM_ERR("user tel number [%.*s] does not respect international format\n"
				,uri.user.len,uri.user.s);
		goto error;
	}

	/* parsing from header */
	if ( parse_from_header( msg )==-1 ) {
		LM_ERR("failed to get FROM header\n");
		goto error;
	}
	from = (struct to_body*)msg->from->parsed;

#if 0
	/* adds contact header into reply */
	if (add_contact(msg,&(uri.user))==-1) {
		LM_ERR("can't build contact for reply\n");
		goto error;
	}
#endif

	/*-------------BUILD AND FILL THE SMS_MSG STRUCTURE --------------------*/
	/* computes the amount of memory needed */
	len = SMS_HDR_BF_ADDR_LEN + from->uri.len
		+ SMS_HDR_AF_ADDR_LEN + body.len + SMS_FOOTER_LEN /*text to send*/
		+ from->uri.len /* from */
		+ uri.user.len-1 /* to user (without '+') */
		+ sizeof(struct sms_msg) ; /* the sms_msg structure */
	/* allocs a new sms_msg structure in shared memory */
	sms_messg = (struct sms_msg*)shm_malloc(len);
	if (!sms_messg) {
		LM_ERR("failed to get shm memory!\n");
		goto error;
	}
	p = (char*)sms_messg + sizeof(struct sms_msg);

	/* copy "from" into sms struct */
	sms_messg->from.len = from->uri.len;
	sms_messg->from.s = p;
	append_str(p,from->uri.s,from->uri.len);

	/* copy "to.user" - we have to strip out the '+' */
	sms_messg->to.len = uri.user.len-1;
	sms_messg->to.s = p;
	append_str(p,uri.user.s+1,sms_messg->to.len);

	/* copy (and composing) sms body */
	sms_messg->text.len = SMS_HDR_BF_ADDR_LEN + sms_messg->from.len
		+ SMS_HDR_AF_ADDR_LEN + body.len+SMS_FOOTER_LEN;
	sms_messg->text.s = p;
	append_str(p, SMS_HDR_BF_ADDR, SMS_HDR_BF_ADDR_LEN);
	append_str(p, sms_messg->from.s, sms_messg->from.len);
	append_str(p, SMS_HDR_AF_ADDR, SMS_HDR_AF_ADDR_LEN);
	append_str(p, body.s, body.len);
	append_str(p, SMS_FOOTER, SMS_FOOTER_LEN);

	if (*queued_msgs>MAX_QUEUED_MESSAGES)
		goto error;
	(*queued_msgs)++;

	if (write(net_pipes_in[net], &sms_messg, sizeof(sms_messg))!=
	sizeof(sms_messg) )
	{
		LM_ERR("error when writing for net %d to pipe [%d] : %s\n",
				net,net_pipes_in[net],strerror(errno) );
		shm_free(sms_messg);
		(*queued_msgs)--;
		goto error;
	}

	return 1;
 error:
	return -1;
}
示例#10
0
/* returns: 0/1 (false/true) or -1 on error, -127 EXPR_DROP */
static int eval_elem(struct expr* e, struct sip_msg* msg)
{

	struct sip_uri uri;
	int ret;
	ret=E_BUG;
	
	if (e->type!=ELEM_T){
		LOG(L_CRIT," BUG: eval_elem: invalid type\n");
		goto error;
	}
	switch(e->l.operand){
		case METHOD_O:
				ret=comp_strstr(&msg->first_line.u.request.method, e->r.param,
								e->op, e->subtype);
				break;
		case URI_O:
				if(msg->new_uri.s){
					if (e->subtype==MYSELF_ST){
						if (parse_sip_msg_uri(msg)<0) ret=-1;
						else	ret=check_self_op(e->op, &msg->parsed_uri.host,
									msg->parsed_uri.port_no?
									msg->parsed_uri.port_no:SIP_PORT);
					}else{
						ret=comp_strstr(&msg->new_uri, e->r.param,
										e->op, e->subtype);
					}
				}else{
					if (e->subtype==MYSELF_ST){
						if (parse_sip_msg_uri(msg)<0) ret=-1;
						else	ret=check_self_op(e->op, &msg->parsed_uri.host,
									msg->parsed_uri.port_no?
									msg->parsed_uri.port_no:SIP_PORT);
					}else{
						ret=comp_strstr(&msg->first_line.u.request.uri,
										 e->r.param, e->op, e->subtype);
					}
				}
				break;
		case FROM_URI_O:
				if (parse_from_header(msg)!=0){
					LOG(L_ERR, "ERROR: eval_elem: bad or missing"
								" From: header\n");
					goto error;
				}
				if (e->subtype==MYSELF_ST){
					if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len,
									&uri) < 0){
						LOG(L_ERR, "ERROR: eval_elem: bad uri in From:\n");
						goto error;
					}
					ret=check_self_op(e->op, &uri.host,
										uri.port_no?uri.port_no:SIP_PORT);
				}else{
					ret=comp_strstr(&get_from(msg)->uri,
							e->r.param, e->op, e->subtype);
				}
				break;
		case TO_URI_O:
				if ((msg->to==0) && ((parse_headers(msg, HDR_TO_F, 0)==-1) ||
							(msg->to==0))){
					LOG(L_ERR, "ERROR: eval_elem: bad or missing"
								" To: header\n");
					goto error;
				}
				/* to content is parsed automatically */
				if (e->subtype==MYSELF_ST){
					if (parse_uri(get_to(msg)->uri.s, get_to(msg)->uri.len,
									&uri) < 0){
						LOG(L_ERR, "ERROR: eval_elem: bad uri in To:\n");
						goto error;
					}
					ret=check_self_op(e->op, &uri.host,
										uri.port_no?uri.port_no:SIP_PORT);
				}else{
					ret=comp_strstr(&get_to(msg)->uri,
										e->r.param, e->op, e->subtype);
				}
				break;
		case SRCIP_O:
				ret=comp_ip(&msg->rcv.src_ip, e->r.param, e->op, e->subtype);
				break;
		case DSTIP_O:
				ret=comp_ip(&msg->rcv.dst_ip, e->r.param, e->op, e->subtype);
				break;
		case NUMBER_O:
				ret=!(!e->r.intval); /* !! to transform it in {0,1} */
				break;
		case ACTION_O:
				ret=run_action_list( (struct action*)e->r.param, msg);
				if (ret<=0) ret=(ret==0)?EXPR_DROP:0;
				else ret=1;
				break;
		case SRCPORT_O:
				ret=comp_no(msg->rcv.src_port, 
					e->r.param, /* e.g., 5060 */
					e->op, /* e.g. == */
					e->subtype /* 5060 is number */);
				break;
		case DSTPORT_O:
				ret=comp_no(msg->rcv.dst_port, e->r.param, e->op, 
							e->subtype);
				break;
		case PROTO_O:
				ret=comp_no(msg->rcv.proto, e->r.param, e->op, e->subtype);
				break;
		case AF_O:
				ret=comp_no(msg->rcv.src_ip.af, e->r.param, e->op, e->subtype);
				break;
		case RETCODE_O:
				ret=comp_no(return_code, e->r.param, e->op, e->subtype);
				break;
		case MSGLEN_O:
				ret=comp_no(msg->len, e->r.param, e->op, e->subtype);
				break;
		default:
				LOG(L_CRIT, "BUG: eval_elem: invalid operand %d\n",
							e->l.operand);
	}
	return ret;
error:
	return -1;
}
示例#11
0
int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri)
{
	contact_t* c;
	int st, mode;
	str aor;
	int ret;
	sip_uri_t *u;
	rr_t *route;
	struct sip_uri puri;
	param_hooks_t hooks;
	param_t *params;
	contact_t *contact;
	int use_ob = 1, use_regid = 1;

	u = parse_to_uri(_m);
	if(u==NULL)
		goto error;

	rerrno = R_FINE;
	ret = 1;

	if (parse_message(_m) < 0) {
		goto error;
	}

	if (check_contacts(_m, &st) > 0) {
		goto error;
	}

	if (parse_supported(_m) == 0) {
		if (!(get_supported(_m)	& F_OPTION_TAG_OUTBOUND)
				&& reg_outbound_mode == REG_OUTBOUND_REQUIRE) {
			LM_WARN("Outbound required by server and not supported by UAC\n");
			rerrno = R_OB_UNSUP;
			goto error;
		}
	}

	if (parse_require(_m) == 0) {
		if ((get_require(_m) & F_OPTION_TAG_OUTBOUND)
				&& reg_outbound_mode == REG_OUTBOUND_NONE) {
			LM_WARN("Outbound required by UAC and not supported by server\n");
			rerrno = R_OB_REQD;
			goto error;
		}
	}

	if (reg_outbound_mode != REG_OUTBOUND_NONE
			&& _m->contact && _m->contact->parsed
			&& !(parse_headers(_m, HDR_VIA2_F, 0) == -1 || _m->via2 == 0
				|| _m->via2->error != PARSE_OK)) {
		/* Outbound supported on server, and more than one Via: - not the first hop */

		if (!(parse_headers(_m, HDR_PATH_F, 0) == -1 || _m->path == 0)) {
			route = (rr_t *)0;
			if (parse_rr_body(_m->path->body.s, _m->path->body.len, &route) < 0) {
				LM_ERR("Failed to parse Path: header body\n");
				goto error;
			}
			if (parse_uri(route->nameaddr.uri.s, route->nameaddr.uri.len, &puri) < 0) {
				LM_ERR("Failed to parse Path: URI\n");
				goto error;
			}
			if (parse_params(&puri.params, CLASS_URI, &hooks, &params) != 0) {
				LM_ERR("Failed to parse Path: URI parameters\n");
				goto error;
			}
			if (!hooks.uri.ob) {
				/* No ;ob parameter to top Path: URI - no outbound */
				use_ob = 0;
			}

		} else {
			/* No Path: header - no outbound */
			use_ob = 0;

		}

		contact = ((contact_body_t *) _m->contact->parsed)->contacts;
		if (!contact) {
			LM_ERR("empty Contact:\n");
			goto error;
		}

		if ((use_ob == 0) && (reg_regid_mode == REG_REGID_OUTBOUND)) {
			if ((get_supported(_m) & F_OPTION_TAG_OUTBOUND)
					&& contact->reg_id) {
				LM_WARN("Outbound used by UAC but not supported by edge proxy\n");
				rerrno = R_OB_UNSUP_EDGE;
				goto error;
			} else {
				/* ignore ;reg-id parameter */
				use_regid = 0;
			}
		}
	}

	get_act_time();
	c = get_first_contact(_m);

	if (extract_aor((_uri)?_uri:&get_to(_m)->uri, &aor, NULL) < 0) {
		LM_ERR("failed to extract Address Of Record\n");
		goto error;
	}

	mem_only = is_cflag_set(REG_SAVE_MEM_FL)?FL_MEM:FL_NONE;

	if (c == 0) {
		if (st) {
			if (star(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error;
			else ret=3;
		} else {
			if (no_contacts(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error;
			else ret=4;
		}
	} else {
		mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0;
		if ((ret=add_contacts(_m, (udomain_t*)_d, &aor, mode, use_regid)) < 0)
			goto error;
		ret = (ret==0)?1:ret;
	}

	update_stat(accepted_registrations, 1);

	/* Only send reply upon request, not upon reply */
	if ((is_route_type(REQUEST_ROUTE) || is_route_type(FAILURE_ROUTE))
			&& !is_cflag_set(REG_SAVE_NORPL_FL) && (reg_send_reply(_m) < 0))
		return -1;

	return ret;
error:
	update_stat(rejected_registrations, 1);
	if (is_route_type(REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) )
		reg_send_reply(_m);

	return 0;
}
示例#12
0
/**
 * sngtc_offer - will remove the SDP body of an early negotiation INVITE and
 * store it in the newly created dialog as a dlg_val.
 *
 * @return: 1 on success, negative on failure
 */
static int sngtc_offer(struct sip_msg *msg)
{
	struct hdr_field *hf;
	struct lump *lump;
	struct dlg_cell *dlg;
	struct sngtc_info *info = NULL;
	str body, totag, st;

	if (dlg_binds.create_dlg(msg, 0) < 0) {
		LM_ERR("failed to create dialog\n");
		return SNGTC_ERR;
	}

	dlg = dlg_binds.get_dlg();
	if (!dlg) {
		LM_ERR("failed to fetch current dialog\n");
		return SNGTC_ERR;
	}

	if (get_body(msg, &body) != 0 || body.len <= 0) {
		LM_ERR("can only do transcoding for early negotiation INVITES\n");
		return SNGTC_SDP_ERR;
	}

	totag = get_to(msg)->tag_value;

	/* INVITE retransmissions will skip this part */
	if (dlg_binds.fetch_dlg_value(dlg, &dlg_key_sngtc_info, &st, 0) != 0) {

		if (store_sngtc_info(dlg, &body) != 0) {
			LM_ERR("failed to create sngtc info struct\n");
			return SNGTC_ERR;
		}

		/* register a callback to free the above */
		if (dlg_binds.register_dlgcb(dlg,
			                         DLGCB_EXPIRED|DLGCB_FAILED|DLGCB_TERMINATED,
		    sngtc_dlg_terminated, NULL, NULL) != 0) {

			LM_ERR("failed to register dialog callback\n");
			return SNGTC_ERR;
		}

	/* for re-INVITES, just recreate the struct sngtc_info */
	} else if (totag.s && totag.len != 0) {
		info = *(struct sngtc_info **)(st.s);

		free_transcoding_sessions(info->sessions);
		if (info->caller_sdp.s)
			shm_free(info->caller_sdp.s);
		if (info->modified_caller_sdp.s)
			shm_free(info->modified_caller_sdp.s);

		if (store_sngtc_info(dlg, &body) != 0) {
			LM_ERR("failed to create sngtc info struct\n");
			return SNGTC_ERR;
		}

		shm_free(info);
	}

	LM_DBG("SDP body:\n");
	LM_DBG("%.*s\n", body.len, body.s);

	hf = msg->content_type;

	/* delete the Content-Type header, we're setting up late negotiation */
	lump = del_lump(msg, hf->name.s - msg->buf, hf->len, HDR_OTHER_T);
	if (!lump) {
		LM_ERR("no more pkg mem\n");
		return SNGTC_ERR;
	}

	/* trim the entire SDP body */
	lump = del_lump(msg, body.s - msg->buf, body.len, HDR_OTHER_T);
	if (!lump) {
		LM_ERR("no more pkg mem\n");
		return SNGTC_ERR;
	}

	return 1;
}
示例#13
0
int dialoginfo_set(struct sip_msg* msg, char* flag_pv, char* str2)
{
	struct dlg_cell * dlg;
	str peer_uri= {0, 0}; /* constructed from TO display name and RURI */
	struct to_body* from, peer_to_body, FROM, *to;
	str* ruri;
	int len =0,ret=-1;
	char flag= DLG_PUB_AB;
	static char buf[256];
	int buf_len= 255;
	str flag_str;
	char caller_buf[256], callee_buf[256];
	pv_value_t tok;

	peer_to_body.param_lst = FROM.param_lst = NULL;

	if (msg->REQ_METHOD != METHOD_INVITE)
		return 1;

	if(dlg_api.create_dlg(msg,0)< 0)
	{
		LM_ERR("Failed to create dialog\n");
		return -1;
	}

	dlg = dlg_api.get_dlg();

	LM_DBG("new INVITE dialog created: from=%.*s\n",
		dlg->from_uri.len, dlg->from_uri.s);

	from = get_from(msg);
	/* if defined overwrite */
	if(caller_spec_param.s) /* if parameter defined */
	{
		memset(&tok, 0, sizeof(pv_value_t));
		if(pv_get_spec_value(msg, &caller_spec, &tok) < 0)  /* if value set */
		{
			LM_ERR("Failed to get caller value\n");
			return -1;
		}
		if(tok.flags&PV_VAL_STR)
		{
			str caller_str;
			if(tok.rs.len + CRLF_LEN > buf_len)
			{
				LM_ERR("Buffer overflow");
				return -1;
			}
			trim(&tok.rs);
			memcpy(caller_buf, tok.rs.s, tok.rs.len);
			len = tok.rs.len;
			if(strncmp(tok.rs.s+len-CRLF_LEN, CRLF, CRLF_LEN))
			{
				memcpy(caller_buf + len, CRLF, CRLF_LEN);
				len+= CRLF_LEN;
			}

			parse_to(caller_buf, caller_buf+len , &FROM);
			if(FROM.error != PARSE_OK)
			{
				LM_ERR("Failed to parse caller specification - not a valid uri\n");
				goto end;
			}
			from = &FROM;
			caller_str.s = caller_buf;
			caller_str.len = len;
			LM_DBG("caller: %*s- len= %d\n", len, caller_buf, len);
			/* store caller in a dlg variable */
			if(dlg_api.store_dlg_value(dlg, &entity_dlg_var, &caller_str)< 0)
			{
				LM_ERR("Failed to store dialog ruri\n");
				goto end;
			}
		}
	}

	peer_uri.s = callee_buf;
	if(callee_spec_param.s)
	{
		memset(&tok, 0, sizeof(pv_value_t));
		if(pv_get_spec_value(msg, &callee_spec, &tok) < 0)
		{
			LM_ERR("Failed to get callee value\n");
			goto end;
		}
		if(tok.flags&PV_VAL_STR)
		{
			if(tok.rs.len + CRLF_LEN > buf_len)
			{
				LM_ERR("Buffer overflow");
				goto end;
			}
			trim(&tok.rs);
			memcpy(peer_uri.s, tok.rs.s, tok.rs.len);
			len = tok.rs.len;
			if(strncmp(tok.rs.s+len-CRLF_LEN, CRLF, CRLF_LEN))
			{
				memcpy(peer_uri.s + len, CRLF, CRLF_LEN);
				len+= CRLF_LEN;
			}
			peer_uri.len = len;
		}
		else
			goto default_callee;
	}
	else
	{
default_callee:
		ruri = GET_RURI(msg);
		to = get_to(msg);
		len= to->display.len + 2 + ruri->len + CRLF_LEN;
		if(len > buf_len)
		{
			LM_ERR("Buffer overflow\n");
			goto end;
		}
		len = 0;
		if(to->display.len && to->display.s)
		{
			memcpy(peer_uri.s, to->display.s, to->display.len);
			peer_uri.s[to->display.len]='<';
			len = to->display.len + 1;
		}
		memcpy(peer_uri.s + len, ruri->s, ruri->len);
		len+= ruri->len;
		if(to->display.len)
		{
			peer_uri.s[len++]='>';
		}
		memcpy(peer_uri.s + len, CRLF, CRLF_LEN);
		len+= CRLF_LEN;
		peer_uri.len = len;
	}
	LM_DBG("Peer uri = %.*s\n", peer_uri.len, peer_uri.s);

	parse_to(peer_uri.s, peer_uri.s+peer_uri.len, &peer_to_body);
	if(peer_to_body.error != PARSE_OK)
	{
		LM_ERR("Failed to peer uri [%.*s]\n", peer_uri.len, peer_uri.s);
		goto end;
	}

	/* store peer uri in dialog structure */
	if(dlg_api.store_dlg_value(dlg, &peer_dlg_var, &peer_uri)< 0)
	{
		LM_ERR("Failed to store dialog ruri\n");
		goto end;
	}

	/* store flag, if defined  */
	if(flag_pv)
	{
		if(pv_printf(msg, (pv_elem_t*)flag_pv, buf, &buf_len)<0)
		{
			LM_ERR("cannot print the format\n");
			goto end;
		}

		if(!check_flag(buf, buf_len))
		{
			LM_ERR("Wrong value for flag\n");
			goto end;
		}
		flag = buf[0];
		flag_str.s = buf;
		flag_str.len = buf_len;
		if(dlg_api.store_dlg_value(dlg, &flag_dlg_var, &flag_str)< 0)
		{
			LM_ERR("Failed to store dialog ruri\n");
			goto end;
		}
	}

	/* register dialog callbacks which triggers sending PUBLISH */
	if (dlg_api.register_dlgcb(dlg,
		DLGCB_FAILED| DLGCB_CONFIRMED | DLGCB_TERMINATED | DLGCB_EXPIRED |
		DLGCB_RESPONSE_WITHIN | DLGCB_EARLY,
		__dialog_sendpublish, 0, 0) != 0) {
		LM_ERR("cannot register callback for interesting dialog types\n");
		goto end;
	}

#ifdef PUA_DIALOGINFO_DEBUG
	/* dialog callback testing (registered last to be executed first) */
	if (dlg_api.register_dlgcb(dlg,
		DLGCB_FAILED| DLGCB_CONFIRMED | DLGCB_REQ_WITHIN | DLGCB_TERMINATED |
		DLGCB_EXPIRED | DLGCB_EARLY | DLGCB_RESPONSE_FWDED |
		DLGCB_RESPONSE_WITHIN  | DLGCB_MI_CONTEXT | DLGCB_DESTROY,
		__dialog_cbtest, NULL, NULL) != 0) {
		LM_ERR("cannot register callback for all dialog types\n");
		goto end;
	}
#endif

        if(publish_on_trying) {
	        if(flag == DLG_PUB_A || flag == DLG_PUB_AB)
		        dialog_publish("trying", from, &peer_to_body, &(dlg->callid), 1, DEFAULT_CREATED_LIFETIME, 0, 0);

	        if(flag == DLG_PUB_B || flag == DLG_PUB_AB)
		        dialog_publish("trying", &peer_to_body, from, &(dlg->callid), 0, DEFAULT_CREATED_LIFETIME, 0, 0);
        }

	ret=1;
end:
	if (peer_to_body.param_lst)
		free_to_params(&peer_to_body);
	if (FROM.param_lst)
		free_to_params(&FROM);
	return ret;
}
示例#14
0
static void
__dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
{
	str tag = {0,0};
	struct to_body from;
	str peer_uri= {0, 0};
	char flag = DLG_PUB_AB;
	str flag_str;
	struct to_body peer_to_body;
	str entity_uri= {0, 0};
	int buf_len = 255;
	struct sip_msg* msg = _params->msg;

	flag_str.s = &flag;
	flag_str.len = 1;

	memset(&from, 0, sizeof(struct to_body));
	memset(&peer_to_body, 0, sizeof(struct to_body));

	from.uri = dlg->from_uri;

	peer_uri.len = buf_len;
	peer_uri.s = (char*)pkg_malloc(buf_len);
	if(peer_uri.s == NULL)
	{
		LM_ERR("No more memory\n");
		goto error;
	}
	/* extract the peer_uri */
	if(dlg_api.fetch_dlg_value(dlg, &peer_dlg_var, &peer_uri, 1) < 0 || peer_uri.len==0)
	{
		LM_ERR("Failed to fetch peer uri dialog variable\n");
		goto error;
	}

	LM_DBG("peer_uri = %.*s\n", peer_uri.len, peer_uri.s);

	parse_to(peer_uri.s, peer_uri.s+peer_uri.len, &peer_to_body);
	if(peer_to_body.error != PARSE_OK)
	{
		LM_ERR("Failed to peer uri [%.*s]\n", peer_uri.len, peer_uri.s);
		goto error;
	}

	/* try to extract the flag */
	dlg_api.fetch_dlg_value(dlg, &flag_dlg_var, &flag_str, 1);
	LM_DBG("flag = %c\n", flag);

	entity_uri.len = buf_len;
	entity_uri.s = (char*)pkg_malloc(buf_len);
	if(entity_uri.s == NULL)
	{
		LM_ERR("No more memory\n");
		goto error;
	}
	/* check if entity is also custom */
	if(dlg_api.fetch_dlg_value(dlg, &entity_dlg_var, &entity_uri, 1) == 0)
	{
		/* overwrite from with this value */
		parse_to(entity_uri.s, entity_uri.s + entity_uri.len, &from);
		if(from.error != PARSE_OK)
		{
			LM_ERR("Wrong format for entity body\n");
			goto error;
		}
		LM_DBG("entity_uri = %.*s\n", entity_uri.len, entity_uri.s);
		LM_DBG("from uri = %.*s\n", from.uri.len, from.uri.s);
	}

	switch (type) {
	case DLGCB_FAILED:
	case DLGCB_TERMINATED:
	case DLGCB_EXPIRED:
		LM_DBG("dialog over, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_A)
			dialog_publish("terminated", &from, &peer_to_body, &(dlg->callid), 1, 0, 0, 0);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_B)
			dialog_publish("terminated", &peer_to_body, &from, &(dlg->callid), 0, 0, 0, 0);
		break;
	case DLGCB_RESPONSE_WITHIN:
		if (get_cseq(msg)->method_id==METHOD_INVITE) {
			if (msg->flags & nopublish_flag) {
				LM_DBG("nopublish flag was set for this INVITE\n");
				break;
			}
			LM_DBG("nopublish flag not set for this INVITE, will publish\n");
		} else {
			/* no publish for non-INVITEs */
			break;
		}
	case DLGCB_CONFIRMED:
		LM_DBG("dialog confirmed, from=%.*s\n", dlg->from_uri.len, dlg->from_uri.s);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_A)
			dialog_publish("confirmed", &from, &peer_to_body, &(dlg->callid), 1, dlg->lifetime, 0, 0);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_B)
			dialog_publish("confirmed", &peer_to_body, &from, &(dlg->callid), 0, dlg->lifetime, 0, 0);
		break;
	case DLGCB_EARLY:
		LM_DBG("dialog is early, from=%.*s\n", from.uri.len, from.uri.s);
		if (include_tags) {
			/* get to tag*/
			if ( !_params->msg->to && ((parse_headers(_params->msg, HDR_TO_F,0)<0) || !_params->msg->to) ) {
				LM_ERR("bad reply or missing TO hdr :-/\n");
				tag.s = 0;
				tag.len = 0;
			} else {
				tag = get_to(_params->msg)->tag_value;
				if (tag.s==0 || tag.len==0) {
					LM_ERR("missing TAG param in TO hdr :-/\n");
					tag.s = 0;
					tag.len = 0;
				}
			}
			if(flag == DLG_PUB_AB || flag == DLG_PUB_A)
			{
				if (caller_confirmed) {
					dialog_publish("confirmed", &from, &peer_to_body, &(dlg->callid), 1,
						dlg->lifetime, &(dlg->legs[DLG_CALLER_LEG].tag), &tag);
				} else {
					dialog_publish("early", &from, &peer_to_body, &(dlg->callid), 1,
						dlg->lifetime, &(dlg->legs[DLG_CALLER_LEG].tag), &tag);
				}
			}

			if(flag == DLG_PUB_AB || flag == DLG_PUB_B)
			{
				dialog_publish("early", &peer_to_body, &from, &(dlg->callid), 0,
					dlg->lifetime, &tag, &(dlg->legs[DLG_CALLER_LEG].tag));
			}
		} else {
			if(flag == DLG_PUB_AB || flag == DLG_PUB_A)
			{
				if (caller_confirmed) {
					dialog_publish("confirmed", &from, &peer_to_body, &(dlg->callid), 1,
						dlg->lifetime, 0, 0);
				} else {
					dialog_publish("early", &from, &peer_to_body, &(dlg->callid), 1,
						dlg->lifetime, 0, 0);
				}
			}
			if(flag == DLG_PUB_AB || flag == DLG_PUB_B)
			{
				dialog_publish("early", &peer_to_body, &from, &(dlg->callid), 0,
					dlg->lifetime, 0, 0);
			}
		}
		break;
	default:
		LM_ERR("unhandled dialog callback type %d received, from=%.*s\n", type, dlg->from_uri.len, dlg->from_uri.s);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_A)
			dialog_publish("terminated", &from, &peer_to_body, &(dlg->callid), 1, 0, 0, 0);
		if(flag == DLG_PUB_AB || flag == DLG_PUB_B)
			dialog_publish("terminated", &peer_to_body, &from, &(dlg->callid), 0, 0, 0, 0);
	}
error:
	if(peer_uri.s)
		pkg_free(peer_uri.s);
	if(entity_uri.s)
		pkg_free(entity_uri.s);
	if (peer_to_body.param_lst)
		free_to_params(&peer_to_body);
	if (from.param_lst)
		free_to_params(&from);
}
示例#15
0
/*Create cell to control Subscriber Dialog States
    This cell save this information:
    - Dialog Id:
        .Callid
        .to_tag
        .from_tag
    - expires
    - Local_uri
    - Remote_uri
    - Notifier_uri
    - INVITE's Callid
    - Event body
    - State
*/
int create_subscriber_cell(struct sip_msg* reply, struct parms_cb* params_cb){

    str* callid = NULL;
    int expires= 0;
    struct to_body *pto= NULL, *pfrom = NULL;
    int size_subs_cell;
    struct sm_subscriber *new_cell = NULL;
    int vsp_addr_len;
    char *vsp_addr = "@vsp.com";
    time_t rawtime;
    int time_now;
    struct sm_subscriber *subs_cell = NULL;

    callid= (str*) pkg_malloc (sizeof (str));
    if (callid == NULL) {
        LM_ERR("--------------------------------------------------no more pkg memory\n");
        return 0;
    }
    /*Verify repĺy is OK and get callid and expires from response*/
    if ( !extract_reply_headers(reply, callid, expires)){
        LM_ERR("fail in extract headers\n");
        return 0;
    }

    /*get From header fields */
    pfrom = get_from(reply);
    LM_INFO("PFROM: %.*s \n ", pfrom->uri.len, pfrom->uri.s );
    if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0){
        LM_ERR("reply without tag value \n");
        return 0;
    }

    /*get To header fields */
    pto = get_to(reply);
    LM_INFO("PTO: %.*s \n ", pto->uri.len, pto->uri.s );
      if (pto == NULL || pto->error != PARSE_OK) {
        LM_ERR("failed to parse TO header\n");
        return 0;
    }

    // get source ip address that send INVITE
    vsp_addr = ip_addr2a(&reply->rcv.src_ip);
    vsp_addr_len = strlen(vsp_addr);

    time(&rawtime);
    time_now = (int)rawtime;
    LM_INFO("TIME : %d \n", (int)rawtime );

    /* build subscriber cell */
    size_subs_cell = sizeof (struct sm_subscriber) + callid->len + pfrom->tag_value.len + pto->tag_value.len + pfrom->uri.len + pto->uri.len + params_cb->callid_ori.len +  params_cb->event.len + vsp_addr_len + 10 ;
    subs_cell = shm_malloc(size_subs_cell + 1);
    if (!subs_cell) {
        LM_ERR("no more shm\n");
        return 0;
    }

    memset(subs_cell, 0, size_subs_cell + 1);
    subs_cell->expires = expires;
    subs_cell->timeout =  TIMER_B + time_now;
    LM_INFO("SUBS_TIMEOUT: %d \n ", subs_cell->timeout );

    subs_cell->dlg_id.callid.len = callid->len;
    subs_cell->dlg_id.callid.s = (char *) (subs_cell + 1);
    memcpy(subs_cell->dlg_id.callid.s, callid->s, callid->len);
    LM_INFO("SUBS_CALLID: %.*s \n ", subs_cell->dlg_id.callid.len, subs_cell->dlg_id.callid.s );

    subs_cell->dlg_id.from_tag.len = pfrom->tag_value.len;
    subs_cell->dlg_id.from_tag.s = (char *) (subs_cell + 1) + callid->len;
    memcpy(subs_cell->dlg_id.from_tag.s, pfrom->tag_value.s, pfrom->tag_value.len);
    LM_INFO("SUBS_FROM_TAG: %.*s \n ", subs_cell->dlg_id.from_tag.len, subs_cell->dlg_id.from_tag.s );

    subs_cell->dlg_id.to_tag.len = pto->tag_value.len;
    subs_cell->dlg_id.to_tag.s = (char *) (subs_cell + 1) + callid->len + pfrom->tag_value.len;
    memcpy(subs_cell->dlg_id.to_tag.s, pto->tag_value.s, pto->tag_value.len);
    LM_INFO("SUBS_TO_TAG: %.*s \n ", subs_cell->dlg_id.to_tag.len, subs_cell->dlg_id.to_tag.s );

    subs_cell->loc_uri.len = pfrom->uri.len;
    subs_cell->loc_uri.s = (char *) (subs_cell + 1) + callid->len + pfrom->tag_value.len + pto->tag_value.len;
    memcpy(subs_cell->loc_uri.s,pfrom->uri.s,pfrom->uri.len);
    LM_INFO("SUBS_LOC_URI: %.*s \n ", subs_cell->loc_uri.len, subs_cell->loc_uri.s );

    subs_cell->rem_uri.len= pto->uri.len;
    subs_cell->rem_uri.s = (char *) (subs_cell + 1) + callid->len + pfrom->tag_value.len + pfrom->uri.len + pto->tag_value.len;
    memcpy(subs_cell->rem_uri.s, pto->uri.s, pto->uri.len);
    LM_INFO("SUBS_REM_URI: %.*s \n ", subs_cell->rem_uri.len, subs_cell->rem_uri.s );

    subs_cell->callid_ori.len= params_cb->callid_ori.len;
    subs_cell->callid_ori.s = (char *) (subs_cell + 1) + callid->len + pfrom->tag_value.len + pfrom->uri.len + pto->tag_value.len + pto->uri.len;
    memcpy(subs_cell->callid_ori.s, params_cb->callid_ori.s, params_cb->callid_ori.len);
    LM_INFO("SUBS_CALLID_ORI: %.*s \n ", subs_cell->callid_ori.len, subs_cell->callid_ori.s );

    subs_cell->event.len= params_cb->event.len;
    subs_cell->event.s = (char *) (subs_cell + 1) + callid->len + pfrom->tag_value.len + pfrom->uri.len + pto->tag_value.len + pto->uri.len + params_cb->callid_ori.len;
    memcpy(subs_cell->event.s, params_cb->event.s, params_cb->event.len);
    LM_INFO("SUBS_EVENT: %.*s \n ", subs_cell->event.len, subs_cell->event.s );

    subs_cell->contact.len = vsp_addr_len + 10;
    subs_cell->contact.s = (char *) (subs_cell + 1) + callid->len + pfrom->tag_value.len + pfrom->uri.len + pto->tag_value.len + pto->uri.len + params_cb->callid_ori.len + params_cb->event.len;
    memcpy(subs_cell->contact.s, "sip:teste@", 10);
    memcpy(subs_cell->contact.s + 10, vsp_addr, vsp_addr_len);
    LM_INFO("SUBS_CONTACT: %.*s \n ", subs_cell->contact.len, subs_cell->contact.s );

    subs_cell -> status = NOTIFY_WAIT;

    /* push cell in Subscriber list linked */
    if (new_cell != NULL) {
        new_cell->next = subs_cell;
        new_cell = subs_cell;
    } else {
        new_cell = subs_cell;
        *subs_pt = new_cell;
    }

    pkg_free(callid);

    return 1;

}
示例#16
0
/*!
 * \brief Function that is registered as RR callback for dialog tracking
 * 
 * Function that is registered as RR callback for dialog tracking. It
 * sets the appropriate events after the SIP method and run the state
 * machine to update the dialog state. It updates then the saved
 * dialogs and also the statistics.
 * \param req SIP request
 * \param route_params record-route parameter
 * \param param unused
 */
void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
{
	dlg_cell_t *dlg;
	dlg_iuid_t *iuid;
	str val, callid, ftag, ttag;
	int h_entry, h_id, new_state, old_state, unref, event, timeout, reset;
	unsigned int dir;
	int ret = 0;

	dlg = dlg_get_ctx_dialog();
	if (dlg!=NULL) {
		dlg_release(dlg);
		return;
	}

	/* skip initial requests - they may end up here because of the
	 * preloaded route */
	if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
		LM_ERR("bad request or missing TO hdr :-/\n");
		return;
	}
	if ( get_to(req)->tag_value.len==0 )
		return;

	dlg = 0;
	dir = DLG_DIR_NONE;

	if ( seq_match_mode!=SEQ_MATCH_NO_ID ) {
		if( d_rrb.get_route_param( req, &rr_param, &val)!=0) {
			LM_DBG("Route param '%.*s' not found\n", rr_param.len,rr_param.s);
			if (seq_match_mode==SEQ_MATCH_STRICT_ID )
				return;
		} else {
			LM_DBG("route param is '%.*s' (len=%d)\n",val.len,val.s,val.len);

			if ( parse_dlg_rr_param( val.s, val.s+val.len, &h_entry, &h_id)<0 )
				return;

			dlg = dlg_lookup(h_entry, h_id);
			if (dlg==0) {
				LM_WARN("unable to find dialog for %.*s "
					"with route param '%.*s' [%u:%u]\n",
					req->first_line.u.request.method.len,
					req->first_line.u.request.method.s,
					val.len,val.s, h_entry, h_id);
				if (seq_match_mode==SEQ_MATCH_STRICT_ID )
					return;
			} else {
				if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0) {
					// lookup_dlg has incremented the ref count by 1
					dlg_release(dlg);
					return;
				}
				if (match_dialog( dlg, &callid, &ftag, &ttag, &dir )==0) {
					LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
							"ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
							req->first_line.u.request.method.len,
							req->first_line.u.request.method.s,
							callid.len, callid.s, callid.len,
							ftag.len, ftag.s, ftag.len,
							ttag.len, ttag.s, ttag.len, dir);
					LM_WARN("dialog identification elements are callid='%.*s'/%d, "
							"caller tag='%.*s'/%d, callee tag='%.*s'/%d\n",
							dlg->callid.len, dlg->callid.s, dlg->callid.len,
							dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
							dlg->tag[DLG_CALLER_LEG].len,
							dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s,
							dlg->tag[DLG_CALLEE_LEG].len);
					// lookup_dlg has incremented the ref count by 1
					dlg_release(dlg);

					// Reset variables in order to do a lookup based on SIP-Elements.
					dlg = 0;
					dir = DLG_DIR_NONE;

					if (seq_match_mode==SEQ_MATCH_STRICT_ID )
						return;
				}
			}
		}
	}

	if (dlg==0) {
		if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0)
			return;
		/* TODO - try to use the RR dir detection to speed up here the
		 * search -bogdan */
		dlg = get_dlg(&callid, &ftag, &ttag, &dir);
		if (dlg==0){
			LM_DBG("Callid '%.*s' not found\n",
				req->callid->body.len, req->callid->body.s);
			return;
		}
	}

    /* set current dialog - re-use ref increment from dlg_get() above */
    set_current_dialog( req, dlg);
    _dlg_ctx.iuid.h_entry = dlg->h_entry;
    _dlg_ctx.iuid.h_id = dlg->h_id;

	if (req->first_line.u.request.method_value != METHOD_ACK) {
		iuid = dlg_get_iuid_shm_clone(dlg);
		if(iuid!=NULL)
		{
			/* register callback for the replies of this request */
			if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_IN|TMCB_ON_FAILURE,
					dlg_onreply, (void*)iuid, dlg_iuid_sfree)<0 ) {
				LM_ERR("failed to register TMCB (3)\n");
				shm_free(iuid);
			}
			iuid = NULL;
		}
	}
	
	/* run state machine */
	switch ( req->first_line.u.request.method_value ) {
		case METHOD_PRACK:
			event = DLG_EVENT_REQPRACK; break;
		case METHOD_ACK:
			event = DLG_EVENT_REQACK; break;
		case METHOD_BYE:
			event = DLG_EVENT_REQBYE; break;
		default:
			event = DLG_EVENT_REQ;
	}

	next_state_dlg( dlg, event, &old_state, &new_state, &unref);

	CURR_DLG_ID = req->id;
	CURR_DLG_LIFETIME = (unsigned int)(time(0))-dlg->start_ts;
	CURR_DLG_STATUS = new_state;

	dlg_run_event_route(dlg, req, old_state, new_state);

	/* delay deletion of dialog until transaction has died off in order
	 * to absorb in-air messages */
	if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
		iuid = dlg_get_iuid_shm_clone(dlg);
		if(iuid!=NULL) {
			if ( d_tmb.register_tmcb(req, NULL, TMCB_DESTROY,
					unref_dlg_from_cb, (void*)iuid, dlg_iuid_sfree)<0 ) {
				LM_ERR("failed to register deletion delay function\n");
				shm_free(iuid);
			} else {
				dlg_ref(dlg, 1);
			}
		}
	}

	if (new_state==DLG_STATE_CONFIRMED && old_state!=DLG_STATE_CONFIRMED)
		dlg_ka_add(dlg);

	/* run actions for the transition */
	if (event==DLG_EVENT_REQBYE && new_state==DLG_STATE_DELETED &&
	old_state!=DLG_STATE_DELETED) {
		LM_DBG("BYE successfully processed\n");
		/* remove from timer */
		ret = remove_dialog_timer(&dlg->tl);
		if (ret < 0) {
			LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
				"with clid '%.*s' and tags '%.*s' '%.*s'\n",
				dlg, dlg->h_entry, dlg->h_id,
				dlg->callid.len, dlg->callid.s,
				dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
				dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
		} else if (ret > 0) {
			LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
				"with clid '%.*s' and tags '%.*s' '%.*s'\n",
				dlg, dlg->h_entry, dlg->h_id,
				dlg->callid.len, dlg->callid.s,
				dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
				dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
		} else {
			/* one extra unref due to removal from timer list */
			unref++;
		}
		/* dialog terminated (BYE) */
        dlg_terminated( req, dlg, dir);

		dlg_unref(dlg, unref);

		_dlg_ctx.cpid = my_pid();
		_dlg_ctx.expect_t = 1;
		dlg_set_ctx_iuid(dlg);

		if_update_stat( dlg_enable_stats, active_dlgs, -1);
		goto done;
	}

	if ( (event==DLG_EVENT_REQ || event==DLG_EVENT_REQACK)
	&& (new_state==DLG_STATE_CONFIRMED || new_state==DLG_STATE_EARLY)) {

		timeout = get_dlg_timeout(req);
		if (timeout!=default_timeout) {
			dlg->lifetime = timeout;
		}
		reset = !((dlg->iflags & DLG_IFLAG_TIMER_NORESET) || dlg_timeout_noreset);

		if ((new_state!=DLG_STATE_EARLY) && (old_state!=DLG_STATE_CONFIRMED || reset)) {
			if (update_dlg_timer( &dlg->tl, dlg->lifetime )==-1) {
				LM_ERR("failed to update dialog lifetime\n");
			} else {
				dlg->dflags |= DLG_FLAG_CHANGED;
			}
		}
		if(event != DLG_EVENT_REQACK) {
			if(update_cseqs(dlg, req, dir)!=0) {
				LM_ERR("cseqs update failed\n");
			} else {
				dlg->dflags |= DLG_FLAG_CHANGED;
			}
		}
		if(dlg_db_mode==DB_MODE_REALTIME && (dlg->dflags&DLG_FLAG_CHANGED)) {
			update_dialog_dbinfo(dlg);
		}

		if (old_state==DLG_STATE_CONFIRMED_NA) {
			LM_DBG("confirming ACK successfully processed\n");

			/* confirming ACK request */
			run_dlg_callbacks( DLGCB_CONFIRMED, dlg, req, NULL, dir, 0);
		} else {
			LM_DBG("sequential request successfully processed\n");

			/* within dialog request */
			run_dlg_callbacks( DLGCB_REQ_WITHIN, dlg, req, NULL, dir, 0);

			if ( (event!=DLG_EVENT_REQACK) &&
					(dlg->cbs.types)&DLGCB_RESPONSE_WITHIN ) {
				iuid = dlg_get_iuid_shm_clone(dlg);
				if(iuid!=NULL)
				{
					/* register callback for the replies of this request */
					if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_FWDED,
							(dir==DLG_DIR_UPSTREAM)?dlg_seq_down_onreply:
														dlg_seq_up_onreply,
							(void*)iuid, dlg_iuid_sfree)<0 ) {
						LM_ERR("failed to register TMCB (2)\n");
						shm_free(iuid);
					}
				}
			}
		}
	}

	if(new_state==DLG_STATE_CONFIRMED && old_state==DLG_STATE_CONFIRMED_NA){
		dlg->dflags |= DLG_FLAG_CHANGED;
		if(dlg_db_mode == DB_MODE_REALTIME)
			update_dialog_dbinfo(dlg);
	}

done:
	dlg_release(dlg);
	return;
}
示例#17
0
/*
 * function that simply prints the parameters passed
 */
static int siprec_start_rec(struct sip_msg *msg, str *srs, str *group,
		str *_cA, str *_cB, str *rtp, str *m_ip)
{
	int ret;
	str *aor, *display, *xml_val;
	struct src_sess *ss;
	struct dlg_cell *dlg;

	/* create the dialog, if does not exist yet */
	dlg = srec_dlg.get_dlg();
	if (!dlg) {
		if (srec_dlg.create_dlg(msg, 0) < 0) {
			LM_ERR("cannot create dialog!\n");
			return -2;
		}
		dlg = srec_dlg.get_dlg();
	}

	/* XXX: if there is a forced send socket in the message, use it
	 * this is the only way to provide a different socket for SRS, but
	 * we might need to take a different approach */
	/* check if the current dialog has a siprec session ongoing */
	if (!(ss = src_new_session(srs, rtp, m_ip, group, msg->force_send_socket))) {
		LM_ERR("cannot create siprec session!\n");
		return -2;
	}

	/* we ref the dialog to make sure it does not dissapear until we receive
	 * the reply from the SRS */
	srec_dlg.ref_dlg(dlg, 1);
	ss->dlg = dlg;

	ret = -2;

	/* caller info */
	if (_cA) {
		xml_val = _cA;
		display = aor = NULL;
	} else {
		if (parse_from_header(msg) < 0) {
			LM_ERR("cannot parse from header!\n");
			goto session_cleanup;
		}
		aor = &get_from(msg)->uri;
		display = (get_from(msg)->display.s ? &get_from(msg)->display : NULL);
		xml_val = NULL;
	}

	if (src_add_participant(ss, aor, display, xml_val, NULL) < 0) {
		LM_ERR("cannot add caller participant!\n");
		goto session_cleanup;
	}
	if (srs_fill_sdp_stream(msg, ss, &ss->participants[0], 0) < 0) {
		LM_ERR("cannot add SDP for caller!\n");
		goto session_cleanup;
	}
	/* caller info */
	if (_cB) {
		xml_val = _cB;
	} else {
		if ((!msg->to && parse_headers(msg, HDR_TO_F, 0) < 0) || !msg->to) {
			LM_ERR("inexisting or invalid to header!\n");
			goto session_cleanup;
		}
		aor = &get_to(msg)->uri;
		display = (get_to(msg)->display.s ? &get_to(msg)->display : NULL);
		xml_val = NULL;
	}

	if (src_add_participant(ss, aor, display, xml_val, NULL) < 0) {
		LM_ERR("cannot add callee pariticipant!\n");
		goto session_cleanup;
	}

	SIPREC_REF_UNSAFE(ss);
	if (srec_tm.register_tmcb(msg, 0, TMCB_RESPONSE_OUT, tm_start_recording,
			ss, src_unref_session) <= 0) {
		LM_ERR("cannot register tm callbacks\n");
		SIPREC_UNREF_UNSAFE(ss);
		goto session_cleanup;
	}
	return 1;

session_cleanup:
	src_free_session(ss);
	return ret;
}
示例#18
0
/*!
 * \brief Function that is registered as TM callback and called on replies
 *
 * Function that is registered as TM callback and called on replies. It
 * parses the reply and set the appropriate event. This is then used to
 * update the dialog state, run eventual dialog callbacks and save or
 * update the necessary informations about the dialog.
 * \see next_state_dlg
 * \param t transaction, unused
 * \param type type of the entered callback
 * \param param saved dialog structure in the callback
 */
static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param)
{
    dlg_cell_t *dlg = NULL;
	dlg_iuid_t *iuid = NULL;
    int new_state, old_state, unref, event;
    str tag;
    sip_msg_t *req = param->req;
	sip_msg_t *rpl = param->rpl;

	if (shutdown_done)
		return;
	iuid = (dlg_iuid_t*)(*param->param);
	dlg = dlg_get_by_iuid(iuid);
	if(dlg==0)
		return;

	unref = 0;
	if (type & (TMCB_RESPONSE_IN|TMCB_ON_FAILURE)) {
		/* Set the dialog context so it is available in onreply_route and failure_route*/
		set_current_dialog(req, dlg);
		dlg_set_ctx_iuid(dlg);
		goto done;
	}

	if (type==TMCB_RESPONSE_FWDED) {
		/* The state does not change, but the msg is mutable in this callback*/
		run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
		goto done;
	}

	if (type==TMCB_DESTROY)
		event = DLG_EVENT_TDEL;
	else if (param->code<200)
		event = DLG_EVENT_RPL1xx;
	else if (param->code<300)
		event = DLG_EVENT_RPL2xx;
	else
		event = DLG_EVENT_RPL3xx;

	next_state_dlg( dlg, event, &old_state, &new_state, &unref);
	dlg_run_event_route(dlg, (rpl==FAKED_REPLY)?NULL:rpl, old_state, new_state);

	if (new_state==DLG_STATE_EARLY) {
		run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
		if (old_state!=DLG_STATE_EARLY)
			if_update_stat(dlg_enable_stats, early_dlgs, 1);
		goto done;
	}

	if (new_state==DLG_STATE_CONFIRMED_NA &&
	old_state!=DLG_STATE_CONFIRMED_NA && old_state!=DLG_STATE_CONFIRMED ) {
		LM_DBG("dialog %p confirmed (ACK pending)\n",dlg);

		 if (rpl != FAKED_REPLY) {
			/* get to tag*/
			if ( !rpl->to && ((parse_headers(rpl, HDR_TO_F,0)<0)
						|| !rpl->to) ) {
				LM_ERR("bad reply or missing TO hdr :-/\n");
				tag.s = 0;
				tag.len = 0;
			} else {
				tag = get_to(rpl)->tag_value;
				if (tag.s==0 || tag.len==0) {
					LM_ERR("missing TAG param in TO hdr :-/\n");
					tag.s = 0;
					tag.len = 0;
				}
			}

			/* save callee's tag, cseq, contact and record route*/
			if (populate_leg_info( dlg, rpl, t, DLG_CALLEE_LEG, &tag) !=0) {
				LM_ERR("could not add further info to the dialog\n");
			}
		 } else {
			 LM_ERR("Faked reply!\n");
		 }

		/* set start time */
		dlg->start_ts = (unsigned int)(time(0));

		/* save the settings to the database,
		 * if realtime saving mode configured- save dialog now
		 * else: the next time the timer will fire the update*/
		dlg->dflags |= DLG_FLAG_NEW;
		if ( dlg_db_mode==DB_MODE_REALTIME )
			update_dialog_dbinfo(dlg);

		if (0 != insert_dlg_timer( &dlg->tl, dlg->lifetime )) {
			LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
				"with clid '%.*s' and tags '%.*s' '%.*s'\n",
				dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
				dlg->callid.len, dlg->callid.s,
				dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
				dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
		} else {
			/* dialog pointer inserted in timer list */
			dlg_ref(dlg, 1);
		}

		/* dialog confirmed (ACK pending) */
		run_dlg_callbacks( DLGCB_CONFIRMED_NA, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);

		if (old_state==DLG_STATE_EARLY)
			if_update_stat(dlg_enable_stats, early_dlgs, -1);

		if (unref) dlg_unref(dlg, unref);
		if_update_stat(dlg_enable_stats, active_dlgs, 1);
		goto done;
	}

	if ( new_state==DLG_STATE_DELETED
				&& (old_state==DLG_STATE_UNCONFIRMED
					|| old_state==DLG_STATE_EARLY) ) {
		LM_DBG("dialog %p failed (negative reply)\n", dlg);
		/* dialog setup not completed (3456XX) */
		run_dlg_callbacks( DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
		if(dlg_wait_ack==1)
			dlg_set_tm_waitack(t, dlg);
		/* do unref */
		if (unref)
			dlg_unref(dlg, unref);
		if (old_state==DLG_STATE_EARLY)
			if_update_stat(dlg_enable_stats, early_dlgs, -1);

		if_update_stat(dlg_enable_stats, failed_dlgs, 1);

		goto done;
	}

	if (unref) dlg_unref(dlg, unref);

done:
	/* unref due to dlg_get_by_iuid() */
	dlg_release(dlg);
	return;
}
示例#19
0
int update_contact(struct sip_msg* msg, char* str1, char* str2)
{
	ua_pres_t* p, hentity;
	str contact;
	struct to_body *pto= NULL, *pfrom = NULL;
	unsigned int hash_code;

	if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
	{
		LM_ERR("when parsing headers\n");
		return -1;
	}

	/* find the record */
	if( msg->callid==NULL || msg->callid->body.s==NULL)
	{
		LM_ERR("cannot parse callid header\n");
		return -1;
	}		
	
	if (!msg->from || !msg->from->body.s)
	{
		LM_ERR("cannot find 'from' header!\n");
		return -1;
	}
	if (msg->from->parsed == NULL)
	{
		if ( parse_from_header( msg )<0 ) 
		{
			LM_ERR("cannot parse From header\n");
			return -1;
		}
	}
	
	pfrom = (struct to_body*)msg->from->parsed;
	
	if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
	{
		LM_ERR("no from tag value present\n");
		return -1;
	}		
	
	if( msg->to==NULL || msg->to->body.s==NULL)
	{
		LM_ERR("cannot parse TO header\n");
		return -1;
	}			

	pto = get_to(msg);
	if (pto == NULL || pto->error != PARSE_OK) {
		LM_ERR("failed to parse TO header\n");
		return -1;
	}

	if( pto->tag_value.s ==NULL || pto->tag_value.len == 0)
	{
		LM_ERR("no to tag value present\n");
		return -1;
	}

	memset( &hentity, 0, sizeof(ua_pres_t));
	/* as we have a NOTIFY, we are looking for any SUBSCRIBER-like
	   entity in the hash (we do not know the exact type) - bogdan */
	hentity.flag = BLA_SUBSCRIBE | XMPP_SUBSCRIBE | XMPP_INITIAL_SUBS |
		MI_SUBSCRIBE | RLS_SUBSCRIBE;
	hentity.watcher_uri= &pto->uri;
	hentity.to_uri= pfrom->uri; 
	hentity.call_id=  msg->callid->body;
	hentity.to_tag= pto->tag_value;
	hentity.from_tag= pfrom->tag_value;
	
	hash_code= core_hash(&hentity.to_uri,hentity.watcher_uri,
				HASH_SIZE);

	/* extract the contact */
	if(msg->contact== NULL || msg->contact->body.s== NULL)
	{
		LM_ERR("no contact header found in 200 OK reply");
		return -1;
	}
	contact= msg->contact->body;

	lock_get(&HashT->p_records[hash_code].lock);

	p= get_dialog(&hentity, hash_code);
	if(p== NULL)
	{
		lock_release(&HashT->p_records[hash_code].lock);
		LM_ERR("no record for the dialog found in hash table\n");
		return -1;
	}

	shm_free(p->remote_contact.s);

	if(!(p->remote_contact.len== contact.len && 
				strncmp(p->remote_contact.s, contact.s, contact.len)==0))
	{
		/* update remote contact */
		shm_free(p->remote_contact.s);
		p->remote_contact.s= (char*)shm_malloc(contact.len);
		if(p->remote_contact.s== NULL)
		{
			LM_ERR("no more shared memory\n");
			lock_release(&HashT->p_records[hash_code].lock);
			return -1;
		}
		memcpy(p->remote_contact.s, contact.s, contact.len);
		p->remote_contact.len= contact.len;
	}

	lock_release(&HashT->p_records[hash_code].lock);

	return 1;

}
示例#20
0
/*!
 * \brief Create a new dialog from a sip message
 *
 * Create a new dialog from a SIP message, register a callback
 * to keep track of the dialog with help of the tm module.
 * This function is either called from the request callback, or
 * from the dlg_manage function in the configuration script.
 * \see dlg_onreq
 * \see w_dlg_manage
 * \param req SIP message
 * \param t transaction
 * \param run_initial_cbs if set zero, initial callbacks are not executed
 * \return 0 on success, -1 on failure
 */ 
int dlg_new_dialog(sip_msg_t *req, struct cell *t, const int run_initial_cbs)
{
	dlg_cell_t *dlg;
	str s;
	str callid;
    str ftag;
    str ttag;
    str req_uri;
    unsigned int dir;
    int mlock;

	dlg = dlg_get_ctx_dialog();
    if(dlg != NULL) {
		dlg_release(dlg);
        return -1;
	}

	if(req->first_line.u.request.method_value != METHOD_INVITE)
		return -1;

    if(pre_match_parse( req, &callid, &ftag, &ttag, 0)<0) {
        LM_WARN("pre-matching failed\n");
        return -1;
    }

    if(ttag.s!=0 && ttag.len!=0)
        return -1;

    if(pv_printf_s(req, ruri_param_model, &req_uri)<0) {
        LM_ERR("error - cannot print the r-uri format\n");
        return -1;
    }
    trim(&req_uri);

	dir = DLG_DIR_NONE;
	mlock = 1;
	/* search dialog by SIP attributes
	 * - if not found, hash table slot is left locked, to avoid races
	 *   to add 'same' dialog on parallel forking or not-handled-yet
	 *   retransmissions. Release slot after linking new dialog */
	dlg = search_dlg(&callid, &ftag, &ttag, &dir);
	if(dlg) {
		mlock = 0;
		if (detect_spirals) {
			if (spiral_detected == 1)
				return 0;

			if ( dlg->state != DLG_STATE_DELETED ) {
				LM_DBG("Callid '%.*s' found, must be a spiraled request\n",
					callid.len, callid.s);
				spiral_detected = 1;

				if (run_initial_cbs)
					run_dlg_callbacks( DLGCB_SPIRALED, dlg, req, NULL,
							DLG_DIR_DOWNSTREAM, 0);
				/* set ctx dlg id shortcuts */
				_dlg_ctx.iuid.h_entry = dlg->h_entry;
				_dlg_ctx.iuid.h_id = dlg->h_id;
				/* search_dlg() has incremented the ref count by 1 */
				dlg_release(dlg);
				return 0;
			}
			dlg_release(dlg);
		}
		/* lock the slot - dlg found, but in dlg_state_deleted, do a new one */
		dlg_hash_lock(&callid);
    }
    spiral_detected = 0;

    dlg = build_new_dlg (&callid /*callid*/,
                         &(get_from(req)->uri) /*from uri*/,
                         &(get_to(req)->uri) /*to uri*/,
                         &ftag/*from_tag*/,
                         &req_uri /*r-uri*/ );

	if (dlg==0) {
		if(likely(mlock==1)) dlg_hash_release(&callid);
		LM_ERR("failed to create new dialog\n");
		return -1;
	}

	/* save caller's tag, cseq, contact and record route*/
	if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG,
			&(get_from(req)->tag_value)) !=0) {
		if(likely(mlock==1)) dlg_hash_release(&callid);
		LM_ERR("could not add further info to the dialog\n");
		shm_free(dlg);
		return -1;
	}

	/* Populate initial varlist: */
	dlg->vars = get_local_varlist_pointer(req, 1);

	/* if search_dlg() returned NULL, slot was kept locked */
	link_dlg(dlg, 0, mlock);
	if(likely(mlock==1)) dlg_hash_release(&callid);

	dlg->lifetime = get_dlg_timeout(req);
	s.s   = _dlg_ctx.to_route_name;
	s.len = strlen(s.s);
	dlg_set_toroute(dlg, &s);
	dlg->sflags |= _dlg_ctx.flags;
	dlg->iflags |= _dlg_ctx.iflags;

	if (dlg_send_bye!=0 || _dlg_ctx.to_bye!=0)
		dlg->iflags |= DLG_IFLAG_TIMEOUTBYE;

    if (run_initial_cbs)  run_create_callbacks( dlg, req);

	/* first INVITE seen (dialog created, unconfirmed) */
	if ( seq_match_mode!=SEQ_MATCH_NO_ID &&
			add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) {
		LM_ERR("failed to add RR param\n");
		goto error;
	}

    if_update_stat( dlg_enable_stats, processed_dlgs, 1);

	_dlg_ctx.cpid = my_pid();
    _dlg_ctx.iuid.h_entry = dlg->h_entry;
    _dlg_ctx.iuid.h_id = dlg->h_id;
    set_current_dialog(req, dlg);

	return 0;

error:
	if (!spiral_detected)
		dlg_unref(dlg, 1);               // undo ref regarding linking
	return -1;
}
示例#21
0
/*!
 * \brief Function that is registered as RR callback for dialog tracking
 *
 * Function that is registered as RR callback for dialog tracking. It
 * sets the appropriate events after the SIP method and run the state
 * machine to update the dialog state. It updates then the saved
 * dialogs and also the statistics.
 * \param req SIP request
 * \param route_params record-route parameter
 * \param param unused
 */
void dlg_onroute(struct sip_msg* req, str *route_params, void *param) {
    struct dlg_cell *dlg;
    str val, callid, ftag, ttag;
    int h_entry, h_id, new_state, old_state, unref, event, timeout;
    unsigned int dir;
    int ret = 0;

    if (current_dlg_pointer != NULL)
        return;

    /* skip initial requests - they may end up here because of the
     * preloaded route */
    if ((!req->to && parse_headers(req, HDR_TO_F, 0) < 0) || !req->to) {
        LM_ERR("bad request or missing TO hdr :-/\n");
        return;
    }
    if (get_to(req)->tag_value.len == 0)
        return;

    dlg = 0;
    dir = DLG_DIR_NONE;

    if (seq_match_mode != SEQ_MATCH_NO_ID) {
        if (d_rrb.get_route_param(req, &rr_param, &val) != 0) {
            LM_DBG("Route param '%.*s' not found\n", rr_param.len, rr_param.s);
            if (seq_match_mode == SEQ_MATCH_STRICT_ID)
                return;
        } else {
            LM_DBG("route param is '%.*s' (len=%d)\n", val.len, val.s, val.len);

            if (parse_dlg_rr_param(val.s, val.s + val.len, &h_entry, &h_id) < 0)
                return;

            dlg = lookup_dlg(h_entry, h_id);
            if (dlg == 0) {
                LM_WARN("unable to find dialog for %.*s "
                        "with route param '%.*s' [%u:%u]\n",
                        req->first_line.u.request.method.len,
                        req->first_line.u.request.method.s,
                        val.len, val.s, h_entry, h_id);
                if (seq_match_mode == SEQ_MATCH_STRICT_ID)
                    return;
            } else {
                if (pre_match_parse(req, &callid, &ftag, &ttag, 1) < 0) {
                    // lookup_dlg has incremented the ref count by 1
                    unref_dlg(dlg, 1);
                    return;
                }
                if (match_dialog(dlg, &callid, &ftag, &ttag, &dir) == 0) {
                    LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
                            "ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
                            req->first_line.u.request.method.len,
                            req->first_line.u.request.method.s,
                            callid.len, callid.s, callid.len,
                            ftag.len, ftag.s, ftag.len,
                            ttag.len, ttag.s, ttag.len, dir);
                    LM_WARN("dialog identification elements are callid='%.*s'/%d, "
                            "caller tag='%.*s'/%d\n",
                            dlg->callid.len, dlg->callid.s, dlg->callid.len,
                            dlg->from_tag.len, dlg->from_tag.s,
                            dlg->from_tag.len);
                    // lookup_dlg has incremented the ref count by 1
                    unref_dlg(dlg, 1);

                    // Reset variables in order to do a lookup based on SIP-Elements.
                    dlg = 0;
                    dir = DLG_DIR_NONE;

                    if (seq_match_mode == SEQ_MATCH_STRICT_ID)
                        return;
                }
            }
        }
    }

    if (dlg == 0) {
        if (pre_match_parse(req, &callid, &ftag, &ttag, 1) < 0)
            return;
        /* TODO - try to use the RR dir detection to speed up here the
         * search -bogdan */
        dlg = get_dlg(&callid, &ftag, &ttag, &dir);
        if (!dlg) {
            LM_DBG("Callid '%.*s' not found\n",
                    req->callid->body.len, req->callid->body.s);
            return;
        }
    }

    /* set current dialog - re-use ref increment from dlg_get() above */
    set_current_dialog(req, dlg);
    _dlg_ctx.dlg = dlg;

    if (d_tmb.register_tmcb(req, NULL, TMCB_REQUEST_FWDED,
            store_dlg_in_tm_cb, (void*) dlg, NULL) < 0) {
        LM_ERR("failed to store dialog in transaction during dialog creation for later reference\n");
    }

    /* run state machine */
    switch (req->first_line.u.request.method_value) {
        case METHOD_PRACK:
            event = DLG_EVENT_REQPRACK;
            break;
        case METHOD_ACK:
            event = DLG_EVENT_REQACK;
            break;
        case METHOD_BYE:
            event = DLG_EVENT_REQBYE;
            break;
        default:
            event = DLG_EVENT_REQ;
    }

    next_state_dlg(dlg, event, &old_state, &new_state, &unref, 0);

    LM_DBG("unref after next state is %i\n", unref);
    CURR_DLG_ID = req->id;
    CURR_DLG_LIFETIME = (unsigned int) (time(0)) - dlg->start_ts;
    CURR_DLG_STATUS = new_state;

    /* run actions for the transition */
    if (event == DLG_EVENT_REQBYE && new_state == DLG_STATE_DELETED &&
            old_state != DLG_STATE_DELETED) {
        LM_DBG("BYE successfully processed\n");
        /* remove from timer */
        ret = remove_dialog_timer(&dlg->tl);
        if (ret < 0) {
            LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
                    "with clid '%.*s' and tags '%.*s'\n",
                    dlg, dlg->h_entry, dlg->h_id,
                    dlg->callid.len, dlg->callid.s,
                    dlg->from_tag.len, dlg->from_tag.s);

        } else if (ret > 0) {
            LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
                    "with clid '%.*s' and tags '%.*s' \n",
                    dlg, dlg->h_entry, dlg->h_id,
                    dlg->callid.len, dlg->callid.s,
                    dlg->from_tag.len, dlg->from_tag.s);

        } else {
            unref++;
        }
        /* dialog terminated (BYE) */
        dlg_terminated(req, dlg, dir);
        unref_dlg(dlg, unref);

        return;
    }

    if ((event == DLG_EVENT_REQ || event == DLG_EVENT_REQACK)
            && new_state == DLG_STATE_CONFIRMED) {

        timeout = get_dlg_timeout(req);
        if (timeout != default_timeout) {
            dlg->lifetime = timeout;
        }
        if (update_dlg_timer(&dlg->tl, dlg->lifetime) == -1) {
            LM_ERR("failed to update dialog lifetime\n");
        }
        if (update_cseqs(dlg, req, dir, &ttag) != 0) {
            LM_ERR("cseqs update failed\n");
        } else {
            dlg->dflags |= DLG_FLAG_CHANGED;
        }

		if(dlg_db_mode==DB_MODE_REALTIME && (dlg->dflags&DLG_FLAG_CHANGED)) {
			update_dialog_dbinfo(dlg);
		}

        if (old_state != DLG_STATE_CONFIRMED) {
            LM_DBG("confirming ACK successfully processed\n");

            /* confirming ACK request */
            run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, NULL, dir, 0);
        } else {
            LM_DBG("sequential request successfully processed\n");

            /* within dialog request */
            run_dlg_callbacks(DLGCB_REQ_WITHIN, dlg, req, NULL, dir, 0);

            if ((event != DLG_EVENT_REQACK) &&
                    (dlg->cbs.types) & DLGCB_RESPONSE_WITHIN) {
                /* ref the dialog as registered into the transaction callback.
                 * unref will be done when the callback will be destroyed */
                ref_dlg(dlg, 1);
                /* register callback for the replies of this request */
                if (d_tmb.register_tmcb(req, 0, TMCB_RESPONSE_FWDED,
                        (dir == DLG_DIR_UPSTREAM) ? dlg_seq_down_onreply : dlg_seq_up_onreply,
                        (void*) dlg, unreference_dialog) < 0) {
                    LM_ERR("failed to register TMCB (2)\n");
                    unref_dlg(dlg, 1);
                }
            }
        }
    }

    if (new_state == DLG_STATE_CONFIRMED && old_state != DLG_STATE_CONFIRMED) {
        dlg->dflags |= DLG_FLAG_CHANGED;

        if(dlg_db_mode == DB_MODE_REALTIME)
        	update_dialog_dbinfo(dlg);
    }

    return;
}
示例#22
0
/* this is the code which decides what and when shall be relayed
   upstream; note well -- it assumes it is entered locked with
   REPLY_LOCK and it returns unlocked!
*/
enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
	unsigned int msg_status, branch_bm_t *cancel_bitmap )
{
	int relay;
	int save_clone;
	char *buf;
	/* length of outbound reply */
	unsigned int res_len;
	int relayed_code;
	struct sip_msg *relayed_msg;
	struct bookmark bm;
	int totag_retr;
	enum rps reply_status;
	/* retransmission structure of outbound reply and request */
	struct retr_buf *uas_rb;
	str cb_s;
	str text;

	/* keep compiler warnings about use of uninit vars silent */
	res_len=0;
	buf=0;
	relayed_msg=0;
	relayed_code=0;
	totag_retr=0;


	/* remember, what was sent upstream to know whether we are
	 * forwarding a first final reply or not */

	/* *** store and relay message as needed *** */
	reply_status = t_should_relay_response(t, msg_status, branch,
		&save_clone, &relay, cancel_bitmap, p_msg );
	LM_DBG("branch=%d, save=%d, relay=%d\n",
		branch, save_clone, relay );

	/* store the message if needed */
	if (save_clone) /* save for later use, typically branch picking */
	{
		if (!store_reply( t, branch, p_msg ))
			goto error01;
	}

	uas_rb = & t->uas.response;
	if (relay >= 0 ) {
		/* initialize sockets for outbound reply */
		uas_rb->activ_type=msg_status;

		t->relaied_reply_branch = relay;

		/* try building the outbound reply from either the current
		 * or a stored message */
		relayed_msg = branch==relay ? p_msg :  t->uac[relay].reply;
		if (relayed_msg==FAKED_REPLY) {
			relayed_code = branch==relay
				? msg_status : t->uac[relay].last_received;

			text.s = error_text(relayed_code);
			text.len = strlen(text.s); /* FIXME - bogdan*/

			if (relayed_code>=180 && t->uas.request->to
					&& (get_to(t->uas.request)->tag_value.s==0
					|| get_to(t->uas.request)->tag_value.len==0)) {
				calc_crc_suffix( t->uas.request, tm_tag_suffix );
				buf = build_res_buf_from_sip_req(
						relayed_code,
						&text,
						&tm_tag,
						t->uas.request, &res_len, &bm );
			} else {
				buf = build_res_buf_from_sip_req( relayed_code,
					&text, 0/* no to-tag */,
					t->uas.request, &res_len, &bm );
			}

		} else {
			/* run callbacks for all types of responses -
			 * even if they are shmem-ed or not */
			if (has_tran_tmcbs(t,TMCB_RESPONSE_FWDED) ) {
				run_trans_callbacks( TMCB_RESPONSE_FWDED, t, t->uas.request,
					relayed_msg, msg_status );
			}
			relayed_code=relayed_msg->REPLY_STATUS;
			buf = build_res_buf_from_sip_res( relayed_msg, &res_len,
							uas_rb->dst.send_sock,0);
			/* remove all lumps which are not in shm
			 * added either by build_res_buf_from_sip_res, or by
			 * the callbacks that have been called with shmem-ed messages - vlad */
			if (branch!=relay) {
				del_notflaged_lumps( &(relayed_msg->add_rm), LUMPFLAG_SHMEM);
				del_notflaged_lumps( &(relayed_msg->body_lumps), LUMPFLAG_SHMEM);
			}
		}
		if (!buf) {
			LM_ERR("no mem for outbound reply buffer\n");
			goto error02;
		}

		/* attempt to copy the message to UAS's shmem:
		   - copy to-tag for ACK matching as well
		   -  allocate little a bit more for provisional as
		      larger messages are likely to follow and we will be
		      able to reuse the memory frag
		*/
		uas_rb->buffer.s = (char*)shm_resize( uas_rb->buffer.s, res_len +
			(msg_status<200 ?  REPLY_OVERBUFFER_LEN : 0));
		if (!uas_rb->buffer.s) {
			LM_ERR("no more share memory\n");
			goto error03;
		}
		uas_rb->buffer.len = res_len;
		memcpy( uas_rb->buffer.s, buf, res_len );
		if (relayed_msg==FAKED_REPLY) { /* to-tags for local replies */
			update_local_tags(t, &bm, uas_rb->buffer.s, buf);
		}
		stats_trans_rpl( relayed_code, (relayed_msg==FAKED_REPLY)?1:0 );

		/* update the status ... */
		t->uas.status = relayed_code;

		if (is_invite(t) && relayed_msg!=FAKED_REPLY
		&& relayed_code>=200 && relayed_code < 300
		&& has_tran_tmcbs( t,
		TMCB_RESPONSE_OUT|TMCB_RESPONSE_PRE_OUT)) {
			totag_retr=update_totag_set(t, relayed_msg);
		}
	}; /* if relay ... */

	UNLOCK_REPLIES( t );

	/* Setup retransmission timer _before_ the reply is sent
	 * to avoid race conditions
	 */
	if (reply_status == RPS_COMPLETED) {
		/* for auth related replies, we do not do retransmission
		   (via set_final_timer()), but only wait for a final
		   reply (put_on_wait() ) - see RFC 3261 (26.3.2.4 DoS Protection) */
		if ((relayed_code != 401) && (relayed_code != 407))
			set_final_timer(t);
		else
			put_on_wait(t);
	}

	/* send it now (from the private buffer) */
	if (relay >= 0) {
		/* run the PRE sending out callback */
		if (!totag_retr && has_tran_tmcbs(t, TMCB_RESPONSE_PRE_OUT) ) {
			cb_s.s = buf;
			cb_s.len = res_len;
			set_extra_tmcb_params( &cb_s, &uas_rb->dst);
			run_trans_callbacks_locked(TMCB_RESPONSE_PRE_OUT,t,t->uas.request,
				relayed_msg, relayed_code);
		}
		SEND_PR_BUFFER( uas_rb, buf, res_len );
		LM_DBG("sent buf=%p: %.9s..., shmem=%p: %.9s\n",
			buf, buf, uas_rb->buffer.s, uas_rb->buffer.s );
		/* run the POST sending out callback */
		if (!totag_retr && has_tran_tmcbs(t, TMCB_RESPONSE_OUT) ) {
			cb_s.s = buf;
			cb_s.len = res_len;
			set_extra_tmcb_params( &cb_s, &uas_rb->dst);
			run_trans_callbacks_locked( TMCB_RESPONSE_OUT, t, t->uas.request,
				relayed_msg, relayed_code);
		}
		pkg_free( buf );
	}

	/* success */
	return reply_status;

error03:
	pkg_free( buf );
error02:
	if (save_clone) {
		if (t->uac[branch].reply!=FAKED_REPLY)
			free_cloned_msg( t->uac[branch].reply );
		t->uac[branch].reply = NULL;
	}
error01:
	text.s = "Reply processing error";
	text.len = sizeof("Reply processing error")-1;
	t_reply_unsafe( t, t->uas.request, 500, &text );
	UNLOCK_REPLIES(t);
	if (is_invite(t)) cancel_uacs( t, *cancel_bitmap );
	/* a serious error occurred -- attempt to send an error reply;
	   it will take care of clean-ups  */

	/* failure */
	return RPS_ERROR;
}
示例#23
0
文件: exec_hf.c 项目: OPSF/uClinux
static int append_fixed_vars(struct sip_msg *msg, struct hf_wrapper **list)
{
	static char tid[MD5_LEN];
	str *uri;
	struct sip_uri parsed_uri, oparsed_uri;
	char *val;
	int val_len;

	/* source ip */
	if (!append_var(EV_SRCIP, ip_addr2a(&msg->rcv.src_ip), 0, list)) {
		LOG(L_ERR, "ERROR: append_var SRCIP failed \n");
		return 0;
	}
	/* request URI */
	uri=msg->new_uri.s && msg->new_uri.len ? 
		&msg->new_uri : &msg->first_line.u.request.uri;
	if (!append_var(EV_RURI, uri->s, uri->len, list )) {
		LOG(L_ERR, "ERROR: append_var URI failed\n");
		return 0;
	}
	/* userpart of request URI */
	if (parse_uri(uri->s, uri->len, &parsed_uri)<0) {
		LOG(L_WARN, "WARNING: append_var: URI not parsed\n");
	} else {
		if (!append_var(EV_USER, parsed_uri.user.s, 
					parsed_uri.user.len, list)) {
			LOG(L_ERR, "ERROR: append_var USER failed\n");
			goto error;
		}
	}
	/* original URI */
	if (!append_var(EV_ORURI, msg->first_line.u.request.uri.s,
				msg->first_line.u.request.uri.len, list)) {
		LOG(L_ERR, "ERROR: append_var O-URI failed\n");
		goto error;
	}
	/* userpart of request URI */
	if (parse_uri(msg->first_line.u.request.uri.s, 
				msg->first_line.u.request.uri.len, 
				&oparsed_uri)<0) {
		LOG(L_WARN, "WARNING: append_var: orig URI not parsed\n");
	} else {
		if (!append_var(EV_OUSER, oparsed_uri.user.s, 
					oparsed_uri.user.len, list)) {
			LOG(L_ERR, "ERROR: append_var OUSER failed\n");
			goto error;
		}
	}
	/* tid, transaction id == via/branch */
	if (!char_msg_val(msg, tid)) {
		LOG(L_WARN, "WARNING: no tid can be determined\n");
		val=0; val_len=0;
	} else {
		val=tid;val_len=MD5_LEN;
	}
	if (!append_var(EV_TID, val,val_len, list)) {
		LOG(L_ERR, "ERROR: append_var TID failed\n");
		goto error;
	}

	/* did, dialogue id == To-tag */
	if (!(msg->to && get_to(msg) ))  {
		LOG(L_ERR, "ERROR: append_var: no to-tag\n");
		val=0; val_len=0;
	} else {
		val=get_to(msg)->tag_value.s;
		val_len=get_to(msg)->tag_value.len;
	}
	if (!append_var(EV_DID, val, val_len, list)) {
		LOG(L_ERR, "ERROR: append_var DID failed\n");
		goto error;
	}
	return 1;
error:
	return 0;
}
示例#24
0
int t_reply_with_body( struct cell *trans, unsigned int code, str *text,
									str *body, str *new_header, str *to_tag )
{
	struct lump_rpl *hdr_lump;
	struct lump_rpl *body_lump;
	str  rpl;
	int  ret;
	struct bookmark bm;
	struct sip_msg* p_msg = trans->uas.request;
	str to_tag_rpl= {0, 0};

	/* add the lumps for new_header and for body (by bogdan) */
	if (new_header && new_header->len) {
		hdr_lump = add_lump_rpl( p_msg, new_header->s,
			new_header->len, LUMP_RPL_HDR );
		if ( !hdr_lump ) {
			LM_ERR("failed to add hdr lump\n");
			goto error;
		}
	} else {
		hdr_lump = 0;
	}

	/* body lump */
	if(body && body->len) {
		body_lump = add_lump_rpl( p_msg, body->s, body->len,
			LUMP_RPL_BODY );
		if (body_lump==0) {
			LM_ERR("failed add body lump\n");
			goto error_1;
		}
	} else {
		body_lump = 0;
	}

	if(to_tag && to_tag->len) {
		rpl.s = build_res_buf_from_sip_req(code, text, to_tag, p_msg,
		 	(unsigned int*)&rpl.len, &bm);
		to_tag_rpl = *to_tag;
	}
	else
	if (code>=180 && p_msg->to && (get_to(p_msg)->tag_value.s==0
			|| get_to(p_msg)->tag_value.len==0)) {
		calc_crc_suffix( p_msg, tm_tag_suffix );
		rpl.s = build_res_buf_from_sip_req(code,text, &tm_tag, p_msg,
				(unsigned int*)&rpl.len, &bm);
		to_tag_rpl.s = tm_tag.s;
		to_tag_rpl.len = TOTAG_VALUE_LEN;
	} else {
		rpl.s = build_res_buf_from_sip_req(code,text, 0 /*no to-tag*/,
			p_msg, (unsigned int*)&rpl.len, &bm);
	}

	/* since the msg (trans->uas.request) is a clone into shm memory, to avoid
	 * memory leak or crashing (lumps are create in private memory) I will
	 * remove the lumps by myself here (bogdan) */
	if ( hdr_lump ) {
		unlink_lump_rpl( p_msg, hdr_lump);
		free_lump_rpl( hdr_lump );
	}
	if( body_lump ) {
		unlink_lump_rpl( p_msg, body_lump);
		free_lump_rpl( body_lump );
	}

	if (rpl.s==0) {
		LM_ERR("failed in doing build_res_buf_from_sip_req()\n");
		goto error;
	}
	ret=_reply_light( trans, rpl.s, rpl.len, code, to_tag_rpl.s, to_tag_rpl.len,
			1 /* lock replies */, &bm );

	/* mark the transaction as replied */
	if (code>=200) set_kr(REQ_RPLD);

	return ret;
error_1:
	if ( hdr_lump ) {
		unlink_lump_rpl( p_msg, hdr_lump);
		free_lump_rpl( hdr_lump );
	}
error:
	return -1;
}
示例#25
0
int save_aux(struct sip_msg* _m, str* forced_binding, char* _d, char* _f, char* _s)
{
	struct save_ctx  sctx;
	contact_t* c;
	contact_t* forced_c;
	int st;
	str uri;
	str flags_s;
	pv_value_t val;

	rerrno = R_FINE;
	memset( &sctx, 0 , sizeof(sctx));
	sctx.max_contacts = -1;

	sctx.flags = 0;
	if (_f && _f[0]!=0) {
		if (fixup_get_svalue( _m, (gparam_p)_f, &flags_s)!=0) {
			LM_ERR("invalid flags parameter");
			return -1;
		}
		for( st=0 ; st< flags_s.len ; st++ ) {
			switch (flags_s.s[st]) {
				case 'm': sctx.flags |= REG_SAVE_MEMORY_FLAG; break;
				case 'r': sctx.flags |= REG_SAVE_NOREPLY_FLAG; break;
				case 's': sctx.flags |= REG_SAVE_SOCKET_FLAG; break;
				case 'v': sctx.flags |= REG_SAVE_PATH_RECEIVED_FLAG; break;
				case 'f': sctx.flags |= REG_SAVE_FORCE_REG_FLAG; break;
				case 'c':
					sctx.max_contacts = 0;
					while (st<flags_s.len-1 && isdigit(flags_s.s[st+1])) {
						sctx.max_contacts = sctx.max_contacts*10 + 
							flags_s.s[st+1] - '0';
						st++;
					}
					break;
				case 'p':
					if (st<flags_s.len-1) {
						st++;
						if (flags_s.s[st]=='2') {
							sctx.flags |= REG_SAVE_PATH_STRICT_FLAG; break; }
						if (flags_s.s[st]=='1') {
							sctx.flags |= REG_SAVE_PATH_LAZY_FLAG; break; }
						if (flags_s.s[st]=='0') {
							sctx.flags |= REG_SAVE_PATH_OFF_FLAG; break; }
					}
				default: LM_WARN("unsuported flag %c \n",flags_s.s[st]);
			}
		}
	}
	if(route_type == ONREPLY_ROUTE)
		sctx.flags |= REG_SAVE_NOREPLY_FLAG;

	/* if no max_contact per AOR is defined, use the global one */
	if (sctx.max_contacts == -1)
		sctx.max_contacts = max_contacts;

	if (parse_message(_m) < 0) {
		goto error;
	}

	if (forced_binding) {
		if (parse_contacts(forced_binding, &forced_c) < 0) {
			LM_ERR("Unable to parse forced binding [%.*s]\n",
				forced_binding->len, forced_binding->s);
			goto error;
		}
		/* prevent processing all the headers from the message */
		reset_first_contact();
		st = 0;
		c = forced_c;
	} else {
		if (check_contacts(_m, &st) > 0) {
			goto error;
		}
		c = get_first_contact(_m);
	}

	get_act_time();

	if (_s) {
		if (pv_get_spec_value( _m, (pv_spec_p)_s, &val)!=0) {
			LM_ERR("failed to get PV value\n");
			return -1;
		}
		if ( (val.flags&PV_VAL_STR)==0 ) {
			LM_ERR("PV vals is not string\n");
			return -1;
		}
		uri = val.rs;
	} else {
		uri = get_to(_m)->uri;
	}


	if (extract_aor( &uri, &sctx.aor) < 0) {
		LM_ERR("failed to extract Address Of Record\n");
		goto error;
	}

	if (c == 0) {
		if (st) {
			if (star((udomain_t*)_d, &sctx) < 0) goto error;
		} else {
			if (no_contacts((udomain_t*)_d, &sctx.aor) < 0) goto error;
		}
	} else {
		if (add_contacts(_m, c, (udomain_t*)_d, &sctx) < 0) goto error;
	}

	update_stat(accepted_registrations, 1);

	if (!is_cflag_set(REG_SAVE_NOREPLY_FLAG) && (send_reply(_m,sctx.flags)<0))
		return -1;

	return 1;
error:
	update_stat(rejected_registrations, 1);

	if ( !is_cflag_set(REG_SAVE_NOREPLY_FLAG) )
		send_reply(_m,sctx.flags);

	return 0;
}
示例#26
0
/*! \brief 
 * \return 0/1 (false/true) or -1 on error, -127 EXPR_DROP 
 */
static int eval_elem(struct expr* e, struct sip_msg* msg, pv_value_t *val)
{

	struct sip_uri uri;
	int ret;
	int retl;
	int retr;
	int ival;
	pv_value_t lval;
	pv_value_t rval;
	char *p;
	int i,n;
	
	ret=E_BUG;
	if (e->type!=ELEM_T){
		LM_CRIT("invalid type\n");
		goto error;
	}
	
	if(val) memset(val, 0, sizeof(pv_value_t));

	switch(e->left.type){
		case METHOD_O:
				ret=comp_strval(msg, e->op, &msg->first_line.u.request.method,
						&e->right);
				break;
		case URI_O:
				if(msg->new_uri.s){
					if (e->right.type==MYSELF_ST){
						if (parse_sip_msg_uri(msg)<0) ret=-1;
						else	ret=check_self_op(e->op, &msg->parsed_uri.host,
									msg->parsed_uri.port_no?
									msg->parsed_uri.port_no:SIP_PORT);
					}else{
						ret=comp_strval(msg, e->op, &msg->new_uri, &e->right);
					}
				}else{
					if (e->right.type==MYSELF_ST){
						if (parse_sip_msg_uri(msg)<0) ret=-1;
						else	ret=check_self_op(e->op, &msg->parsed_uri.host,
									msg->parsed_uri.port_no?
									msg->parsed_uri.port_no:SIP_PORT);
					}else{
						ret=comp_strval(msg, e->op,
								&msg->first_line.u.request.uri,
								&e->right);
					}
				}
				break;
		case FROM_URI_O:
				if (parse_from_header(msg)<0){
					LM_ERR("bad or missing From: header\n");
					goto error;
				}
				if (e->right.type==MYSELF_ST){
					if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len,
									&uri) < 0){
						LM_ERR("bad uri in From:\n");
						goto error;
					}
					ret=check_self_op(e->op, &uri.host,
										uri.port_no?uri.port_no:SIP_PORT);
				}else{
					ret=comp_strval(msg, e->op, &get_from(msg)->uri,
							&e->right);
				}
				break;
		case TO_URI_O:
				if ((msg->to==0) && ((parse_headers(msg, HDR_TO_F, 0)==-1) ||
							(msg->to==0))){
					LM_ERR("bad or missing To: header\n");
					goto error;
				}
				/* to content is parsed automatically */
				if (e->right.type==MYSELF_ST){
					if (parse_uri(get_to(msg)->uri.s, get_to(msg)->uri.len,
									&uri) < 0){
						LM_ERR("bad uri in To:\n");
						goto error;
					}
					ret=check_self_op(e->op, &uri.host,
										uri.port_no?uri.port_no:SIP_PORT);
				}else{
					ret=comp_strval(msg, e->op, &get_to(msg)->uri,
										&e->right);
				}
				break;
		case SRCIP_O:
				ret=comp_ip(msg, e->op, &msg->rcv.src_ip, &e->right);
				break;
		case DSTIP_O:
				ret=comp_ip(msg, e->op, &msg->rcv.dst_ip, &e->right);
				break;
		case NUMBER_O:
				ret=!(!e->right.v.n); /* !! to transform it in {0,1} */
				break;
		case ACTION_O:
				ret=run_action_list( (struct action*)e->right.v.data, msg);
				if(val)
				{
					val->flags = PV_TYPE_INT|PV_VAL_INT;
					val->ri = ret;
				}
				if (ret<=0) ret=(ret==0)?EXPR_DROP:0;
				else ret=1;
				return ret;
		case EXPR_O:
				retl = retr = 0;
				memset(&lval, 0, sizeof(pv_value_t));
				memset(&rval, 0, sizeof(pv_value_t));
				if(e->left.v.data)
					retl=eval_expr((struct expr*)e->left.v.data,msg,&lval);
				if(lval.flags == PV_VAL_NONE)
				{
					pv_value_destroy(&lval);
					pv_value_destroy(&rval);
					return 0;
				}
				if(e->op == BNOT_OP)
				{
					if(lval.flags&PV_VAL_INT)
					{
						if(val!=NULL)
						{
							val->flags = PV_TYPE_INT|PV_VAL_INT;
							val->ri = ~lval.ri;
						}
						pv_value_destroy(&lval);
						pv_value_destroy(&rval);
						return (val->ri)?1:0;
					}
					LM_ERR("binary NOT on non-numeric value\n");
					pv_value_destroy(&lval);
					pv_value_destroy(&rval);
					return 0;
				}
				if(e->right.v.data)
					retr=eval_expr((struct expr*)e->right.v.data,msg,&rval);
			
				if(lval.flags&PV_TYPE_INT)
				{
					if( (rval.flags&PV_VAL_NULL) )
					{
						rval.ri = 0;
					} else if(!(rval.flags&PV_VAL_INT))
					{
						LM_ERR("invalid numeric operands\n");
						pv_value_destroy(&lval);
						pv_value_destroy(&rval);
						return 0;
					}
					if(val!=NULL)
						val->flags = PV_TYPE_INT|PV_VAL_INT;

					ival = 0;
					switch(e->op) {
						case PLUS_OP:
							ival = lval.ri + rval.ri;
							break;
						case MINUS_OP:
							ival = lval.ri - rval.ri;
							break;
						case DIV_OP:
							if(rval.ri==0)
							{
								LM_ERR("divide by 0\n");
								pv_value_destroy(&lval);
								pv_value_destroy(&rval);
								return 0;
							} else 
								ival = lval.ri / rval.ri;
							break;
						case MULT_OP:
							ival = lval.ri * rval.ri;
							break;
						case MODULO_OP:
							if(rval.ri==0)
							{
								LM_ERR("divide by 0\n");
								pv_value_destroy(&lval);
								pv_value_destroy(&rval);
								return 0;
							} else 
								ival = lval.ri % rval.ri;
							break;
						case BAND_OP:
							ival = lval.ri & rval.ri;
							break;
						case BOR_OP:
							ival = lval.ri | rval.ri;
							break;
						case BXOR_OP:
							ival = lval.ri ^ rval.ri;
							break;
						case BLSHIFT_OP:
							ival = lval.ri << rval.ri;
							break;
						case BRSHIFT_OP:
							ival = lval.ri >> rval.ri;
							break;
						default:
							LM_ERR("invalid int op %d\n", e->op);
								val->ri = 0;
							pv_value_destroy(&lval);
							pv_value_destroy(&rval);
							return 0;
					}
					pv_value_destroy(&lval);
					pv_value_destroy(&rval);
					if(val!=NULL) val->ri = ival;
					return (ival)?1:0;
				} else if (e->op == PLUS_OP) {
					if( (rval.flags&PV_VAL_NULL) || (val==NULL)) {
						if (val) val->flags|=PV_VAL_STR;
						ret = (lval.rs.len>0 || rval.rs.len>0);
						pv_value_destroy(&lval);
						pv_value_destroy(&rval);
						return ret;
					}
					if(!(rval.flags&PV_VAL_STR))
					{
						LM_ERR("invalid string operands\n");
						pv_value_destroy(&lval);
						pv_value_destroy(&rval);
						return 0;
					}
					val->rs.s=(char*)pkg_malloc((lval.rs.len+rval.rs.len+1)
							*sizeof(char));
					if(val->rs.s==0)
					{
						LM_ERR("no more memory\n");
						pv_value_destroy(&lval);
						pv_value_destroy(&rval);
						return 0;
					}
					val->flags = PV_VAL_PKG|PV_VAL_STR;
					memcpy(val->rs.s, lval.rs.s, lval.rs.len);
					memcpy(val->rs.s+lval.rs.len, rval.rs.s, rval.rs.len);
					val->rs.len = lval.rs.len + rval.rs.len;
					val->rs.s[val->rs.len] = '\0';
					pv_value_destroy(&lval);
					pv_value_destroy(&rval);
					return 1;
				} else if ((lval.flags & PV_VAL_STR) && (rval.flags & PV_VAL_STR)) {
					if (lval.rs.len != rval.rs.len)
					{
						LM_ERR("Different length string operands\n");
						pv_value_destroy(&lval);
						pv_value_destroy(&rval);
						return 0;
					}
					n = lval.rs.len;
					val->rs.s = pkg_malloc(n+1);
					if (!val->rs.s)
					{
						LM_ERR("no more memory\n");
						pv_value_destroy(&lval);
						pv_value_destroy(&rval);
						return 0;
					}
					switch(e->op) {
						case BAND_OP:
							for (i=0;i<n;i++)
								val->rs.s[i] = lval.rs.s[i] & rval.rs.s[i];
							break;
						case BOR_OP:
							for (i=0;i<n;i++)
								val->rs.s[i] = lval.rs.s[i] | rval.rs.s[i];
							break;
						case BXOR_OP:
							for (i=0;i<n;i++)
								val->rs.s[i] = lval.rs.s[i] ^ rval.rs.s[i];
							break;
						default:
							LM_ERR("Only bitwise operations can be applied on strings\n");
							val->ri = 0;
							pv_value_destroy(&lval);
							pv_value_destroy(&rval);
							return 0;
					}
					val->flags = PV_VAL_PKG|PV_VAL_STR;
					val->rs.len = n;
					val->rs.s[n] = '\0';
					pv_value_destroy(&lval);
					pv_value_destroy(&rval);
					return 1;
				}
				else {
					LM_ERR("Invalid operator : %d \n",e->op);
					pv_value_destroy(&lval);
					pv_value_destroy(&rval);
					return 0;
				}
				break;
		case SRCPORT_O:
				ret=comp_no(msg->rcv.src_port, 
					e->right.v.data, /* e.g., 5060 */
					e->op, /* e.g. == */
					e->right.type /* 5060 is number */);
				break;
		case DSTPORT_O:
				ret=comp_no(msg->rcv.dst_port, e->right.v.data, e->op, 
							e->right.type);
				break;
		case PROTO_O:
				ret=comp_no(msg->rcv.proto, e->right.v.data, e->op,
						e->right.type);
				break;
		case AF_O:
				ret=comp_no(msg->rcv.src_ip.af, e->right.v.data, e->op,
						e->right.type);
				break;
		case RETCODE_O:
				ret=comp_no(return_code, e->right.v.data, e->op,
						e->right.type);
				break;
		case MSGLEN_O:
				ret=comp_no(msg->len, e->right.v.data, e->op,
						e->right.type);
				break;
		case STRINGV_O:
				if(val) {
					val->flags = PV_VAL_STR;
					val->rs = e->left.v.s;
				}
				/* optimization for no dup ?!?! */
				return (e->left.v.s.len>0)?1:0;
		case NUMBERV_O:
				if(val) {
					val->flags = PV_TYPE_INT|PV_VAL_INT;
					val->ri = e->left.v.n;
				}
				ret=!(!e->left.v.n); /* !! to transform it in {0,1} */
				return ret;
		case SCRIPTVAR_O:
				if(e->op==NO_OP)
				{
					memset(&rval, 0, sizeof(pv_value_t));
					if(pv_get_spec_value(msg, e->right.v.spec, &rval)==0)
					{
						if(rval.flags==PV_VAL_NONE || (rval.flags&PV_VAL_NULL)
								|| (rval.flags&PV_VAL_EMPTY)
								|| ((rval.flags&PV_TYPE_INT)&&rval.ri==0))
						{
							pv_value_destroy(&rval);
							return 0;
						}
						if(rval.flags&PV_TYPE_INT)
						{
							pv_value_destroy(&rval);
							return 1;
						}
						if(rval.rs.len!=0)
						{
							pv_value_destroy(&rval);
							return 1;
						}
						pv_value_destroy(&rval);
					}
					return 0;
				}
				if(e->op==VALUE_OP)
				{
					if(pv_get_spec_value(msg, e->left.v.spec, &lval)==0)
					{
						if(val!=NULL)
							memcpy(val, &lval, sizeof(pv_value_t));
						if(lval.flags&PV_VAL_STR)
						{
							if(!((lval.flags&PV_VAL_PKG) 
									|| (lval.flags&PV_VAL_SHM)))
							{
								if(val!=NULL)
								{
									/* do pkg duplicate */
									p = (char*)pkg_malloc((val->rs.len+1)
											*sizeof(char));
									if(p==0)
									{
										LM_ERR("no more pkg memory\n");
										memset(val, 0, sizeof(pv_value_t));
										return 0;
									}
									memcpy(p, val->rs.s, val->rs.len);
									p[val->rs.len] = 0;
									val->rs.s = p;
									val->flags|= PV_VAL_PKG;
								}
							}
							return 1;
						}
						if(lval.flags==PV_VAL_NONE 
								|| (lval.flags & PV_VAL_NULL)
								|| (lval.flags & PV_VAL_EMPTY))
							return 0;
						if(lval.flags&PV_TYPE_INT)
							return (lval.ri!=0);
						else
							return (lval.rs.len>0);
					}
					return 0;
				}

				ret=comp_scriptvar(msg, e->op, &e->left, &e->right);
				break;
		default:
				LM_CRIT("invalid operand %d\n", e->left.type);
	}
示例#27
0
int tps_request_sent(sip_msg_t *msg, int dialog, int direction, int local)
{
	tps_data_t mtsd;
	tps_data_t stsd;
	tps_data_t *ptsd;
	str lkey;

	memset(&mtsd, 0, sizeof(tps_data_t));
	memset(&stsd, 0, sizeof(tps_data_t));
	ptsd = &mtsd;

	if(tps_pack_request(msg, &mtsd)<0) {
		LM_ERR("failed to extract and pack the headers\n");
		return -1;
	}

	if(direction==TPS_DIR_DOWNSTREAM) {
		lkey = get_from(msg)->tag_value;
	} else {
		lkey = get_to(msg)->tag_value;
	}
	tps_storage_lock_get(&lkey);
	if(dialog==0) {
		if(tps_storage_record(msg, ptsd)<0) {
			goto error;
		}
	}

	/* local generated requests */
	if(local) {
		/* ACK and CANCEL go downstream */
		if(get_cseq(msg)->method_id==METHOD_ACK
				|| get_cseq(msg)->method_id==METHOD_CANCEL
				|| local==2) {
			// th_mask_callid(&msg);
			goto done;
		} else {
			/* should be for upstream */
			goto done;
		}
	}

	tps_remove_headers(msg, HDR_RECORDROUTE_T);
	tps_remove_headers(msg, HDR_CONTACT_T);
	tps_remove_headers(msg, HDR_VIA_T);

	tps_reinsert_via(msg, ptsd, &ptsd->x_via1);
	if(direction==TPS_DIR_UPSTREAM) {
		tps_reinsert_contact(msg, ptsd, &ptsd->as_contact);
	} else {
		tps_reinsert_contact(msg, ptsd, &ptsd->bs_contact);
	}

done:
	tps_storage_lock_release(&lkey);
	return 0;

error:
	tps_storage_lock_release(&lkey);
	return -1;
}
示例#28
0
void dlg_bridge_tm_callback(struct cell *t, int type, struct tmcb_params *ps)
{
	struct sip_msg *msg = NULL;
	dlg_transfer_ctx_t *dtc = NULL;
	struct dlg_cell *dlg = NULL;
	str s;
	str cseq;
	str empty = {"", 0};

	if(ps->param==NULL || *ps->param==0)
	{
		LM_DBG("message id not received\n");
		return;
	}
	dtc = *((dlg_transfer_ctx_t**)ps->param);
	if(dtc==NULL)
		return;
	LM_DBG("completed with status %d\n", ps->code);
	if(ps->code>=300)
		goto error;

	/* 2xx - build dialog/send refer */
	msg = ps->rpl;
	if((msg->cseq==NULL || parse_headers(msg,HDR_CSEQ_F,0)<0)
			|| msg->cseq==NULL || msg->cseq->parsed==NULL)
	{
			LM_ERR("bad sip message or missing CSeq hdr :-/\n");
			goto error;
	}
	cseq = (get_cseq(msg))->number;

	if((msg->to==NULL && parse_headers(msg, HDR_TO_F,0)<0) || msg->to==NULL)
	{
		LM_ERR("bad request or missing TO hdr\n");
		goto error;
	}
	if(parse_from_header(msg))
	{
		LM_ERR("bad request or missing FROM hdr\n");
		goto error;
	}
	if((msg->callid==NULL && parse_headers(msg,HDR_CALLID_F,0)<0)
			|| msg->callid==NULL){
		LM_ERR("bad request or missing CALLID hdr\n");
		goto error;
	}
	s = msg->callid->body;
	trim(&s);

	/* some sanity checks */
	if (s.len==0 || get_from(msg)->tag_value.len==0) {
		LM_ERR("invalid request -> callid (%d) or from TAG (%d) empty\n",
			s.len, get_from(msg)->tag_value.len);
		goto error;
	}

	dlg = build_new_dlg(&s /*callid*/, &(get_from(msg)->uri) /*from uri*/,
		&(get_to(msg)->uri) /*to uri*/,
		&(get_from(msg)->tag_value)/*from_tag*/,
		&(get_to(msg)->uri) /*use to as r-uri*/ );
	if (dlg==0) {
		LM_ERR("failed to create new dialog\n");
		goto error;
	}
	dtc->dlg = dlg;
	if (dlg_set_leg_info(dlg, &(get_from(msg)->tag_value),
				&empty, &dlg_bridge_controller, &cseq, DLG_CALLER_LEG)!=0) {
		LM_ERR("dlg_set_leg_info failed\n");
		goto error;
	}

	if (populate_leg_info(dlg, msg, t, DLG_CALLEE_LEG,
			&(get_to(msg)->tag_value)) !=0)
	{
		LM_ERR("could not add further info to the dialog\n");
		shm_free(dlg);
		goto error;
	}

	if(dlg_refer_callee(dtc)!=0)
		goto error;
	return;

error:
	dlg_transfer_ctx_free(dtc);
	return;
}
示例#29
0
/* look for subscriber cell using callid and to_tag of Notify*/
struct sm_subscriber* get_subs_cell(struct sip_msg *msg, str callid_event) {
	str callid;
	str method;
	struct to_body *pto= NULL, *pfrom = NULL;
	struct sm_subscriber* s;
	unsigned int hash_code;

	method.s = msg->first_line.u.request.method.s;
	method.len = msg->first_line.u.request.method.len;

	if ( parse_headers(msg,HDR_EOH_F, 0) == -1 ){
		LM_ERR("error in parsing headers\n");
		return NULL;
	}

	// get callid from Notify
	if( msg->callid==NULL || msg->callid->body.s==NULL){
		LM_ERR("reply without callid header\n");
		return NULL;
	}
	callid = msg->callid->body;
	LM_DBG("CALLID: %.*s \n ", callid.len, callid.s );

	if (msg->from->parsed == NULL){
		if ( parse_from_header( msg )<0 ){
			LM_ERR("reply without From header\n");
			return NULL;
		}
	}

	//get From header from Notify
	pfrom = get_from(msg);
	LM_DBG("PFROM: %.*s \n ", pfrom->uri.len, pfrom->uri.s );

	if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0){
		LM_ERR("reply without tag value \n");
		return NULL;
	}
	if( msg->to==NULL || msg->to->body.s==NULL){
		LM_ERR("error in parse TO header\n");
		return NULL;
	}

	// get To header from Notify
	pto = get_to(msg);
	if (pto == NULL || pto->error != PARSE_OK) {
		LM_ERR("failed to parse TO header\n");
		return NULL;
	}
	if( pto->tag_value.s ==NULL || pto->tag_value.len == 0){
		LM_ERR("reply without tag value \n");
	}
	LM_DBG("PTO: %.*s \n ", pto->uri.len, pto->uri.s );
	LM_DBG("PTO_TAG: %.*s \n ", pto->tag_value.len, pto->tag_value.s );
	LM_DBG("********************************************CALLID_STR%.*s\n", callid_event.len, callid_event.s);
	hash_code= core_hash(&callid_event, 0, subst_size);
	LM_DBG("********************************************HASH_CODE%d\n", hash_code);



	s= search_shtable(subs_htable, &callid, &pfrom->tag_value, hash_code, &method);
	if (s == NULL) {
		LM_ERR(" ---FAILURE SUB_CELL NOT FOUND IN SHTABLE\n");
	}

	return s;
}
示例#30
0
int sl_send_reply_helper(struct sip_msg *msg ,int code, str *text)
{
	str buf;
	union sockaddr_union to;
	char *dset;
	int dset_len;
	struct bookmark dummy_bm;
	int backup_mhomed;
	int ret;

	if ( msg->REQ_METHOD==METHOD_ACK)
		return 0;

	update_sock_struct_from_ip( &to, msg );

	/* if that is a redirection message, dump current message set to it */
	if (code>=300 && code<400) {
		dset=print_dset(msg, &dset_len);
		if (dset) {
			add_lump_rpl(msg, dset, dset_len, LUMP_RPL_HDR);
		}
	}

	/* add a to-tag if there is a To header field without it */
	if ( code>=180 &&
		(msg->to || (parse_headers(msg,HDR_TO_F, 0)!=-1 && msg->to))
		&& (get_to(msg)->tag_value.s==0 || get_to(msg)->tag_value.len==0) ) 
	{
		calc_crc_suffix( msg, tag_suffix );
		buf.s = build_res_buf_from_sip_req( code, text, &sl_tag, msg,
			(unsigned int*)&buf.len, &dummy_bm);
	} else {
		buf.s = build_res_buf_from_sip_req( code, text, 0, msg,
			(unsigned int*)&buf.len, &dummy_bm);
	}
	if (!buf.s) {
		LM_ERR("response building failed\n");
		goto error;
	}

	run_sl_callbacks( SLCB_REPLY_OUT, msg, &buf, code, text, &to );

	/* supress multhoming support when sending a reply back -- that makes sure
	   that replies will come from where requests came in; good for NATs
	   (there is no known use for mhomed for locally generated replies;
	    note: forwarded cross-interface replies do benefit of mhomed!
	*/
	backup_mhomed=mhomed;
	mhomed=0;
	/* use for sending the received interface -bogdan*/
	ret = msg_send( msg->rcv.bind_address, msg->rcv.proto, &to,
			msg->rcv.proto_reserved1, buf.s, buf.len);
	mhomed=backup_mhomed;
	pkg_free(buf.s);

	if (ret<0)
		goto error;

	*(sl_timeout) = get_ticks() + SL_RPL_WAIT_TIME;

	update_sl_reply_stat(code);

	return 1;

error:
	return -1;
}