Example #1
0
    int
sca_dialog_create_replaces_header( sca_dialog *dlg, str *replaces_hdr )
{
    int		len;

    assert( replaces_hdr != NULL );

    if ( SCA_STR_EMPTY( &dlg->call_id ) || SCA_STR_EMPTY( &dlg->from_tag ) ||
		SCA_STR_EMPTY( &dlg->to_tag )) {
	LM_ERR( "sca_dialog_create_replaces_header: dialog %.*s is not a "
		"confirmed dialog, cannot build Replaces header",
		STR_FMT( &dlg->id ));
	return( -1 );
    }

    memset( replaces_hdr, 0, sizeof( str ));

    /* +2 for semicolons separating tags, +2 for CRLF */
    replaces_hdr->s = pkg_malloc( SCA_REPLACES_HDR_PREFIX_LEN +
				  SCA_REPLACES_TO_TAG_LEN +
				  SCA_REPLACES_FROM_TAG_LEN +
				  dlg->id.len + 2 + 2 );

    memcpy( replaces_hdr->s, SCA_REPLACES_HDR_PREFIX,
	    SCA_REPLACES_HDR_PREFIX_LEN );
    len = SCA_REPLACES_HDR_PREFIX_LEN;

    memcpy( replaces_hdr->s + len, dlg->call_id.s, dlg->call_id.len );
    len += dlg->call_id.len;

    memcpy( replaces_hdr->s + len, ";", strlen( ";" ));
    len += strlen( ";" );

    memcpy( replaces_hdr->s + len, SCA_REPLACES_TO_TAG,
	    SCA_REPLACES_TO_TAG_LEN );
    len += SCA_REPLACES_TO_TAG_LEN;
    memcpy( replaces_hdr->s + len, dlg->to_tag.s, dlg->to_tag.len );
    len += dlg->to_tag.len;

    memcpy( replaces_hdr->s + len, ";", strlen( ";" ));
    len += strlen( ";" );

    memcpy( replaces_hdr->s + len, SCA_REPLACES_FROM_TAG,
	    SCA_REPLACES_FROM_TAG_LEN );
    len += SCA_REPLACES_FROM_TAG_LEN;
    memcpy( replaces_hdr->s + len, dlg->from_tag.s, dlg->from_tag.len );
    len += dlg->from_tag.len;

    memcpy( replaces_hdr->s + len, CRLF, CRLF_LEN );
    len += CRLF_LEN;

    replaces_hdr->len = len;

    return( len );
}
Example #2
0
    int
sca_aor_create_from_info( str *aor, uri_type type, str *user, str *domain,
	str *port )
{
    str		scheme = STR_NULL;
    int		len = 0;

    assert( aor != NULL );

    uri_type_to_str( type, &scheme );

    /* +1 for ':', +1 for '@' */
    len = scheme.len + 1 + user->len + 1 + domain->len;
    if ( !SCA_STR_EMPTY( port )) {
	/* +1 for ':' */
	len += 1 + port->len;
    }

    aor->s = (char *)pkg_malloc( len );
    if ( aor->s == NULL ) {
	LM_ERR( "sca_aor_create_from_info: pkg_malloc %d bytes failed", len );
	return( -1 );
    }

    len = 0;
    SCA_STR_COPY( aor, &scheme );
    len += scheme.len;

    *(aor->s + len) = ':';
    aor->len++;
    len++;

    SCA_STR_APPEND( aor, user );
    len += user->len;

    *(aor->s + len) = '@';
    aor->len++;
    len++;

    SCA_STR_APPEND( aor, domain );
    len += domain->len;

    if ( !SCA_STR_EMPTY( port )) {
	*(aor->s + len) = ':';
	len += 1;

	SCA_STR_APPEND( aor, port );
	len += port->len;
    }

    return( aor->len );
}
Example #3
0
/* count characters requiring escape as defined by escape_common */
    int
sca_uri_display_escapes_count( str *display )
{
    int			c = 0;
    int			i;

    if ( SCA_STR_EMPTY( display )) {
	return( 0 );
    }

    for ( i = 0; i < display->len; i++ ) {
	switch ( display->s[ i ] ) {
	case '\'':
	case '"':
	case '\\':
	case '\0':
	    c++;
	    
	default:
	    break;
	}
    }

    return( c );
}
Example #4
0
    int
sca_get_msg_from_header( sip_msg_t *msg, struct to_body **from )
{
    struct to_body	*f;

    assert( msg != NULL );
    assert( from != NULL );

    if ( SCA_HEADER_EMPTY( msg->from )) {
	LM_ERR( "Empty From header" );
	return( -1 );
    }
    if ( parse_from_header( msg ) < 0 ) {
	LM_ERR( "Bad From header" );
	return( -1 );
    }
    f = get_from( msg );
    if ( SCA_STR_EMPTY( &f->tag_value )) {
	LM_ERR( "Bad From header: no tag parameter" );
	return( -1 );
    }

    /* ensure the URI is parsed for future use */
    if ( parse_uri( f->uri.s, f->uri.len, GET_FROM_PURI( msg )) < 0 ) {
	LM_ERR( "Failed to parse From URI %.*s", STR_FMT( &f->uri ));
	return( -1 );
    }

    *from = f;

    return( 0 );
}
Example #5
0
    void *
sca_hash_table_index_kv_find( sca_hash_table *ht, int slot_idx, str *key )
{
    assert( ht != NULL && !SCA_STR_EMPTY( key ));
    assert( slot_idx >= 0 && slot_idx < ht->size );

    return( sca_hash_table_slot_kv_find( &ht->slots[ slot_idx ], key ));
}
Example #6
0
    int
sca_dialog_build_from_tags( sca_dialog *dialog, int maxlen, str *call_id,
	str *from_tag, str *to_tag )
{
    int		len = 0;

    assert( dialog != NULL && dialog->id.s != NULL );
    assert( call_id != NULL );
    assert( from_tag != NULL );

    len = call_id->len + from_tag->len;
    if ( !SCA_STR_EMPTY( to_tag )) {
	len += to_tag->len;
    }

    if ( len >= maxlen ) {
	LM_ERR( "sca_dialog_build_from_tags: tags too long" );
	return( -1 );
    }

    memcpy( dialog->id.s, call_id->s, call_id->len );
    dialog->call_id.s = dialog->id.s;
    dialog->call_id.len = call_id->len;

    memcpy( dialog->id.s + call_id->len, from_tag->s, from_tag->len );
    dialog->from_tag.s = dialog->id.s + call_id->len;
    dialog->from_tag.len = from_tag->len;

    if ( !SCA_STR_EMPTY( to_tag )) {
	memcpy( dialog->id.s + call_id->len + from_tag->len,
		to_tag->s, to_tag->len );
	dialog->to_tag.s = dialog->id.s + call_id->len + from_tag->len;
	dialog->to_tag.len = to_tag->len;
    }
    dialog->id.len = len;

    return( len );
}
Example #7
0
static dlg_t *sca_notify_dlg_for_subscription(sca_subscription *sub)
{
	dlg_t *dlg = NULL;

	dlg = (dlg_t *) pkg_malloc(sizeof(dlg_t));
	if (dlg == NULL) {
		LM_ERR("pkg_malloc dlg_t for %.*s failed: out of memory\n",
				STR_FMT(&sub->subscriber));
		goto error;
	}
	memset(dlg, 0, sizeof(dlg_t));

	dlg->loc_seq.value = sub->dialog.notify_cseq;
	dlg->loc_seq.is_set = 1;

	dlg->id.call_id = sub->dialog.call_id;
	dlg->id.rem_tag = sub->dialog.from_tag;
	dlg->id.loc_tag = sub->dialog.to_tag;

	// RURI
	dlg->rem_target = sub->subscriber;

	// To and From URIs are both the SCA AoR in an SCA NOTIFY
	dlg->loc_uri = sub->target_aor;
	dlg->rem_uri = sub->target_aor;

	// restore route
	if (!SCA_STR_EMPTY(&sub->rr)) {
		if (parse_rr_body(sub->rr.s, sub->rr.len, &dlg->route_set) < 0) {
			LM_ERR("sca_notify_dlg_for_subscription: failed to parse "
					"%.*s subscription's Record-Route info\n",
					STR_FMT(&sub->subscriber));
			goto error;
		}
	}

	// the dialog state in an SCA NOTIFY should always be confirmed,
	// since we generated the dialog to-tag in our response to the
	// subscriber's SUBSCRIBE request.
	dlg->state = DLG_CONFIRMED;

	return (dlg);

	error: if (dlg != NULL) {
		pkg_free(dlg);
	}

	return (NULL);
}
Example #8
0
    sca_hash_entry *
sca_hash_table_slot_kv_find_entry_unsafe( sca_hash_slot *slot, str *key )
{
    sca_hash_entry	*e = NULL;

    assert( slot != NULL && !SCA_STR_EMPTY( key ));

    for ( e = slot->entries; e != NULL; e = e->next ) {
	if ( e->compare( key, e->value ) == 0 ) {
	    break;
	}
    }

    return( e );
}
Example #9
0
    int
sca_hash_table_kv_insert( sca_hash_table *ht, str *key, void *value,
	int (*e_compare)(str *, void *), void (*e_description)(void *),
	void (*e_free)(void *))
{
    int		hash_idx;
    int		rc;

    assert( ht != NULL && !SCA_STR_EMPTY( key ) && value != NULL );

    hash_idx = sca_hash_table_index_for_key( ht, key );
    rc = sca_hash_table_index_kv_insert( ht, hash_idx, value, e_compare,
					 e_description, e_free );

    return( rc );
}
Example #10
0
/*
 * send a call-info NOTIFY to all subscribers to a given SCA AoR.
 */
int sca_notify_call_info_subscribers(sca_mod *scam, str *subscription_aor)
{
	sca_hash_slot *slot;
	sca_hash_entry *e;
	sca_subscription *sub;
	str headers = STR_NULL;
	str hash_key = STR_NULL;
	char hdrbuf[SCA_HEADERS_MAX_LEN];
	char keybuf[512];
	char *event_name;
	int slot_idx;
	int rc = -1;

	assert(scam->subscriptions != NULL);
	assert(!SCA_STR_EMPTY(subscription_aor));

	LM_DBG("Notifying ALL subscribers of AOR %.*s due to a SUBSCRIBTION request\n",
			STR_FMT(subscription_aor));

	event_name = sca_event_name_from_type(SCA_EVENT_TYPE_CALL_INFO);
	if (subscription_aor->len + strlen(event_name) >= sizeof(keybuf)) {
		LM_ERR("Hash key %.*s + %s is too long\n",
				STR_FMT(subscription_aor), event_name);
		return (-1);
	}
	hash_key.s = keybuf;
	SCA_STR_COPY(&hash_key, subscription_aor);
	SCA_STR_APPEND_CSTR(&hash_key, event_name);

	slot_idx = sca_hash_table_index_for_key(scam->subscriptions, &hash_key);
	slot = sca_hash_table_slot_for_index(scam->subscriptions, slot_idx);

	sca_hash_table_lock_index(scam->subscriptions, slot_idx);

	for (e = slot->entries; e != NULL; e = e->next) {
		sub = (sca_subscription *) e->value;
		if (!SCA_STR_EQ(subscription_aor, &sub->target_aor)) {
			continue;
		}

		if (headers.len == 0) {
			headers.s = hdrbuf;

			if (sca_notify_build_headers_from_info(&headers, sizeof(hdrbuf),
					scam, sub, SCA_CALL_INFO_APPEARANCE_INDEX_ANY) < 0) {
				LM_ERR("Failed to build NOTIFY headers\n");
				goto done;
			}
		}

		// XXX would like this to be wrapped in one location
		sub->dialog.notify_cseq += 1;

		if (sca_notify_subscriber_internal(scam, sub, &headers) < 0) {
			goto done;
		}
	}
	rc = 1;

	done:
	sca_hash_table_unlock_index(scam->subscriptions, slot_idx);

	return (rc);
}
Example #11
0
    int
sca_create_canonical_aor_for_ua( sip_msg_t *msg, str *c_aor, int ua_opts )
{
    struct to_body	*tf = NULL;
    sip_uri_t		c_uri;
    str			tf_aor = STR_NULL;
    str			contact_uri = STR_NULL;
    int			rc = -1;

    assert( msg != NULL );
    assert( c_aor != NULL );

    memset( c_aor, 0, sizeof( str ));

    if (( ua_opts & SCA_AOR_TYPE_AUTO )) {
	if ( msg->first_line.type == SIP_REQUEST ) {
	    ua_opts = SCA_AOR_TYPE_UAC;
	} else {
	    ua_opts = SCA_AOR_TYPE_UAS;
	}
    }

    if (( ua_opts & SCA_AOR_TYPE_UAC )) {
	if ( sca_get_msg_from_header( msg, &tf ) < 0 ) {
	    LM_ERR( "sca_create_canonical_aor: failed to get From header" );
	    goto done;
	}
    } else {
	if ( sca_get_msg_to_header( msg, &tf ) < 0 ) {
	    LM_ERR( "sca_create_canonical_aor: failed to get To header" );
	    goto done;
	}
    }

    if ( sca_uri_extract_aor( &tf->uri, &tf_aor ) < 0 ) {
	LM_ERR( "sca_create_canonical_aor: failed to extract AoR from "
		"URI <%.*s>", STR_FMT( &tf->uri ));
	goto done;
    }

    memset( &c_uri, 0, sizeof( sip_uri_t ));
    if (( rc = sca_get_msg_contact_uri( msg, &contact_uri )) < 0 ) {
	LM_ERR( "sca_create_canonical_aor: failed to get contact URI from "
		"Contact <%.*s>", STR_FMT( &msg->contact->body ));
	goto done;
    }
    if ( rc > 0 ) {
	if ( parse_uri( contact_uri.s, contact_uri.len, &c_uri ) < 0 ) {
	    LM_ERR( "sca_create_canonical_aor: failed to parse Contact URI "
		    "<%.*s>", STR_FMT( &contact_uri ));
	    rc = -1;
	    goto done;
	}
    }

    if ( SCA_STR_EMPTY( &c_uri.user ) ||
	    SCA_STR_EQ( &c_uri.user, &tf->parsed_uri.user )) {
	/* empty contact header or Contact user matches To/From AoR */
	c_aor->s = (char *)pkg_malloc( tf_aor.len );
	c_aor->len = tf_aor.len;
	memcpy( c_aor->s, tf_aor.s, tf_aor.len );
    } else {
	/* Contact user and To/From user mismatch */
	if ( sca_aor_create_from_info( c_aor, c_uri.type,
		&c_uri.user, &tf->parsed_uri.host,
		&tf->parsed_uri.port ) < 0 ) {
	    LM_ERR( "sca_create_canonical_aor: failed to create AoR from "
		    "Contact <%.*s> and URI <%.*s>",
		    STR_FMT( &contact_uri ), STR_FMT( &tf_aor ));
	    goto done;
	}
    }

    rc = 1;

done:
    return( rc );
}