struct list* define(char* name, char* replacement)
{
    struct list* node;
    unsigned hash_value;

    if ((node = lookup(name)) == NULL)
    {
        node = malloc(sizeof(struct list));

        if (node == NULL || (node->name = str_duplicate(name)) == NULL)
        {
            return NULL;
        }

        hash_value = hash(name);
        node->next = hash_table[hash_value];
        hash_table[hash_value] = node;
    }
    else
    {
        free(node->replacement);
    }

    if ((node->replacement = str_duplicate(replacement)) == NULL)
    {
        return NULL;
    }

    return node;
}
예제 #2
0
/* inserts an item to table, and removes the least item if the table is full */
int addcert2table(ttable *ptable, tcert_item *pcert)
{
	tcert_item *pshmcert;
	unsigned int uhash;

	if (!(pshmcert=(tcert_item *)shm_malloc(sizeof(*pshmcert)))) {
		LOG(L_ERR, "AUTH_IDENTITY:addcert2table: No enough shared memory\n");
		return -1;
	}
	memset(pshmcert, 0, sizeof(*pshmcert));
	if (str_duplicate(&pshmcert->surl, &pcert->surl))
		return -2;

	if (str_duplicate(&pshmcert->scertpem, &pcert->scertpem))
		return -3;

	pshmcert->ivalidbefore=pcert->ivalidbefore;
	pshmcert->uaccessed=1;

	uhash=get_hash1_raw(pcert->surl.s, pcert->surl.len) & (CERTIFICATE_TABLE_ENTRIES-1);

	if (insert_into_table(ptable, (void*)pshmcert, uhash))
		return -4;

	return 0;
}
예제 #3
0
파일: dlg.c 프로젝트: AndreyRybkin/kamailio
/*
 * set dialog's request uri and destination uri (optional)
 */
int set_dlg_target(dlg_t* _d, str* _ruri, str* _duri) {

	if (!_d || !_ruri) {
		LOG(L_ERR, "set_dlg_target(): Invalid parameter value\n");
		return -1;
	}

	if (_d->rem_target.s) shm_free(_d->rem_target.s);
	if (_d->dst_uri.s) {
		shm_free(_d->dst_uri.s);
		_d->dst_uri.s = 0;
		_d->dst_uri.len = 0;
	}

	if (str_duplicate(&_d->rem_target, _ruri)) return -1;
	if (_duri && _duri->len) {
		if (str_duplicate(&_d->dst_uri, _duri)) return -1;
	}

	if (calculate_hooks(_d) < 0) {
		LOG(L_ERR, "set_dlg_target(): Error while calculating hooks\n");
		return -1;
	}

	return 0;
}
예제 #4
0
파일: dlg.c 프로젝트: AndreyRybkin/kamailio
/*
 * Create a new dialog
 */
int new_dlg_uac(str* _cid, str* _ltag, unsigned int _lseq, str* _luri, str* _ruri, dlg_t** _d)
{
	dlg_t* res;
	str generated_cid;
	str generated_ltag;

	if (!_cid) { /* if not given, compute new one */
		generate_callid(&generated_cid);
		_cid = &generated_cid;
	}
	if (_cid && (!_ltag)) { /* if not given, compute new one */
		generate_fromtag(&generated_ltag, _cid);
		_ltag = &generated_ltag;
	}
	if (_lseq == 0) _lseq = DEFAULT_CSEQ;

	if (!_cid || !_ltag || !_luri || !_ruri || !_d) {
		LOG(L_ERR, "new_dlg_uac(): Invalid parameter value\n");
		return -1;
	}

	res = (dlg_t*)shm_malloc(sizeof(dlg_t));
	if (res == 0) {
		LOG(L_ERR, "new_dlg_uac(): No memory left\n");
		return -2;
	}

	     /* Clear everything */	
	memset(res, 0, sizeof(dlg_t));
	
	     /* Make a copy of Call-ID */
	if (str_duplicate(&res->id.call_id, _cid) < 0) return -3;
	     /* Make a copy of local tag (usually From tag) */
	if (str_duplicate(&res->id.loc_tag, _ltag) < 0) return -4;
	     /* Make a copy of local URI (usually From) */
	if (str_duplicate(&res->loc_uri, _luri) < 0) return -5;
	     /* Make a copy of remote URI (usually To) */
	if (str_duplicate(&res->rem_uri, _ruri) < 0) return -6;
	     /* Make a copy of local sequence (usually CSeq) */
	res->loc_seq.value = _lseq;
	     /* And mark it as set */
	res->loc_seq.is_set = 1;

	*_d = res;

	if (calculate_hooks(*_d) < 0) {
		LOG(L_ERR, "new_dlg_uac(): Error while calculating hooks\n");
		/* FIXME: free everything here */
		shm_free(res);
		return -2;
	}
#ifdef DIALOG_CALLBACKS
	run_new_dlg_callbacks(DLG_CB_UAC, res, 0);
#endif
	
	return 0;
}
예제 #5
0
파일: dlg.c 프로젝트: AndreyRybkin/kamailio
/*
 * Extract all information from a request 
 * and update a dialog structure
 */
static inline int request2dlg(struct sip_msg* _m, dlg_t* _d)
{
	str contact, rtag, callid;

	if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
		LOG(L_ERR, "request2dlg(): Error while parsing headers");
		return -1;
	}

	if (get_contact_uri(_m, &contact) < 0) return -2;
	if (contact.len) {
		if (_d->rem_target.s) shm_free(_d->rem_target.s);
		if (_d->dst_uri.s) {
			shm_free(_d->dst_uri.s);
			_d->dst_uri.s = 0;
			_d->dst_uri.len = 0;
		}
		if (str_duplicate(&_d->rem_target, &contact) < 0) return -3;
	}
	
	if (get_from_tag(_m, &rtag) < 0) goto err1;
	if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;

	if (get_callid(_m, &callid) < 0) goto err2;
	if (callid.len && str_duplicate(&_d->id.call_id, &callid) < 0) goto err2;

	if (get_cseq_value(_m, &_d->rem_seq.value) < 0) goto err3;
	_d->rem_seq.is_set = 1;

	if (get_dlg_uri(_m->from, &_d->rem_uri) < 0) goto err3;
	if (get_dlg_uri(_m->to, &_d->loc_uri) < 0) goto err4;

	if (get_route_set(_m, &_d->route_set, NORMAL_ORDER) < 0) goto err5;	

	return 0;
 err5:
	if (_d->loc_uri.s) shm_free(_d->loc_uri.s);
	_d->loc_uri.s = 0;
	_d->loc_uri.len = 0;
 err4:
	if (_d->rem_uri.s) shm_free(_d->rem_uri.s);
	_d->rem_uri.s = 0;
	_d->rem_uri.len = 0;
 err3:
	if (_d->id.call_id.s) shm_free(_d->id.call_id.s);
	_d->id.call_id.s = 0;
	_d->id.call_id.len = 0;
 err2:
	if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
	_d->id.rem_tag.s = 0;
	_d->id.rem_tag.len = 0;
 err1:
	if (_d->rem_target.s) shm_free(_d->rem_target.s);
	_d->rem_target.s = 0;
	_d->rem_target.len = 0;
	return -4;
}
예제 #6
0
파일: dlg.c 프로젝트: AndreyRybkin/kamailio
/*
 * Establishing a new dialog, UAS side
 */
int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d)
{
	dlg_t* res;
	str tag;

	if (!_req || /*!_tag ||*/ !_d) {
		LOG(L_ERR, "new_dlg_uas(): Invalid parameter value\n");
		return -1;
	}

	if (_code > 299) {
		DBG("new_dlg_uas(): Status code >= 300, no dialog created\n");
	}

	res = (dlg_t*)shm_malloc(sizeof(dlg_t));
	if (res == 0) {
		LOG(L_ERR, "new_dlg_uac(): No memory left\n");
		return -3;
	}
	     /* Clear everything */
	memset(res, 0, sizeof(dlg_t));	

	if (request2dlg(_req, res) < 0) {
		LOG(L_ERR, "new_dlg_uas(): Error while converting request to dialog\n");
		free_dlg(res);
		return -4;
	}

	if (_code > 100) {
		tag.s = tm_tags;
		tag.len = TOTAG_VALUE_LEN;
		calc_crc_suffix(_req, tm_tag_suffix);
		if (str_duplicate(&res->id.loc_tag, &tag) < 0) {
			free_dlg(res);
			return -5;
		}
	}
	
	*_d = res;

	if (_code < 100)
		(*_d)->state = DLG_NEW;
	else if (_code < 200)
		(*_d)->state = DLG_EARLY;
	else
		(*_d)->state = DLG_CONFIRMED;

	if (calculate_hooks(*_d) < 0) {
		LOG(L_ERR, "new_dlg_uas(): Error while calculating hooks\n");
		free_dlg(res);
		return -6;
	}
#ifdef DIALOG_CALLBACKS
	run_new_dlg_callbacks(DLG_CB_UAS, res, _req);
#endif

	return 0;
}
예제 #7
0
/*
 * Extract all necessary information from a response and put it
 * in a dialog structure
 */
static inline int response2dlg(struct sip_msg* _m, dlg_t* _d)
{
	str contact, rtag;
	rtag.s=0;

	     /* Parse the whole message, we will need all Record-Route headers */
	if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
		LOG(L_ERR, "response2dlg(): Error while parsing headers\n");
		return -1;
	}
	
	if (get_contact_uri(_m, &contact) < 0) return -2;
	if (_d->rem_target.s) {
		shm_free(_d->rem_target.s);
		_d->rem_target.s = 0; 
		_d->rem_target.len = 0;
	}
	if (_d->dst_uri.s) {
		shm_free(_d->dst_uri.s);
		_d->dst_uri.s = 0; 
		_d->dst_uri.len = 0;
	}
	if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
	
	if (get_to_tag(_m, &rtag) < 0) goto err1;
	//Its unlikely needed to update the tag with responses but for some reason i do it
	if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s); 
	
	if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;
	
	if (_d->route_set) shm_free_rr(&_d->route_set);
	if (get_route_set(_m, &_d->route_set, REVERSE_ORDER) < 0) goto err2;

	return 0;
 err2:
	if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
	_d->id.rem_tag.s = 0;
	_d->id.rem_tag.len = 0;

 err1:
	if (_d->rem_target.s) shm_free(_d->rem_target.s);
	_d->rem_target.s = 0;
	_d->rem_target.len = 0;
	return -4;
}
예제 #8
0
파일: dlg.c 프로젝트: AndreyRybkin/kamailio
/*
 * Handle dialog in DLG_CONFIRMED state, we will be processing
 * a response to a request sent within a dialog
 */
static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m, 
		target_refresh_t is_target_refresh)
{
	int code;
	str contact;

	code = _m->first_line.u.reply.statuscode;	

	     /* Dialog has been already confirmed, that means we received
	      * a response to a request sent within the dialog. We will
	      * update remote target URI if and only if the message sent was
	      * a target refresher. 
	      */

	     /* IF we receive a 481 response, terminate the dialog because
	      * the remote peer indicated that it didn't have the dialog
	      * state anymore, signal this termination with a positive return
	      * value
	      */
	if (code == 481) {
		_d->state = DLG_DESTROYED;
		return 1;
	}

	     /* Do nothing if not 2xx */
	if ((code < 200) || (code >= 300)) return 0;
	
	if (refresh_dialog_resp(_m, is_target_refresh)) {
		     /* Get contact if any and update remote target */
		if (parse_headers(_m, HDR_CONTACT_F, 0) == -1) {
			LOG(L_ERR, "dlg_confirmed_resp_uac(): Error while parsing headers\n");
			return -2;
		}

		     /* Try to extract contact URI */
		if (get_contact_uri(_m, &contact) < 0) return -3;
		     /* If there is a contact URI */
		if (contact.len) {
			     /* Free old remote target and destination uri if any */
			if (_d->rem_target.s) shm_free(_d->rem_target.s);
			if (_d->dst_uri.s) {
				shm_free(_d->dst_uri.s);
				_d->dst_uri.s = 0;
				_d->dst_uri.len = 0;
			}
				
			     /* Duplicate new remote target */
			if (str_duplicate(&_d->rem_target, &contact) < 0) return -4;
		}

		if (calculate_hooks(_d) < 0)
			return -1;
	}

	return 0;
}
예제 #9
0
파일: format.c 프로젝트: dizhaung/SeciHttp
/* Parse and insert output fields from format string */
void parse_format_string(char *str) {
        char *name, *tmp, *i;
        int num_nodes = 0;
        size_t len;

#ifdef DEBUG
        ASSERT(str);
#endif

        len = strlen(str);
        if (len == 0)
                LOG_DIE("Empty format string provided");

        /* Make a temporary copy of the string so we don't modify the original */
        if ((tmp = str_duplicate(str)) == NULL)
                LOG_DIE("Cannot allocate memory for format string buffer");

        for (i = tmp; (name = strtok(i, ",")); i = NULL) {
                /* Normalize input field text */
                name = str_strip_whitespace(name);
                name = str_tolower(name);
                len = strlen(name);

                if (len == 0) continue;
                if (insert_field(name, len)) num_nodes++;
        }

        free(tmp);

        if (num_nodes == 0)
                LOG_DIE("No valid fields found in format string");

#ifdef DEBUG
        int j, num_buckets = 0, num_chain, max_chain = 0;
        FORMAT_NODE *node;

        for (j = 0; j < HASHSIZE; j++) {
                if (fields[j]) num_buckets++;

                num_chain = 0;
                for (node = fields[j]; node != NULL; node = node->next) num_chain++;
                if (num_chain > max_chain) max_chain = num_chain;
        }

        PRINT("----------------------------");
        PRINT("Hash buckets:       %d", HASHSIZE);
        PRINT("Nodes inserted:     %d", num_nodes);
        PRINT("Buckets in use:     %d", num_buckets);
        PRINT("Hash collisions:    %d", num_nodes - num_buckets);
        PRINT("Longest hash chain: %d", max_chain);
        PRINT("----------------------------");
#endif

        return;
}
예제 #10
0
void *parser(void *arg) {
    struct input_args *in_args = (struct input_args *)arg;
    while (1) {
        struct page *page = (struct page *)unbounded_buffer_get(in_args->page_queue);
        if (page == NULL)
            break;
        char *start = page->content;
        while ((start = strstr(start, "link:")) != NULL) {
            if (start > page->content && *(start - 1) != ' ' && *(start - 1) != '\n') {
                start = start + 5;
                continue;
            }
            char *end = start + 5;
            while (*end != ' ' && *end != '\n' && *end != '\0')
                end++;
            if (*end == '\0') {
                char *url = str_duplicate(start + 5);
                in_args->edge(page->url, url);
                bounded_buffer_put(in_args->url_queue, (void *)url);
                break;
            } else {
                char tmp = *end;
                *end = '\0';
                char *url = str_duplicate(start + 5);
                in_args->edge(page->url, url);
                bounded_buffer_put(in_args->url_queue, (void *)url);
                *end = tmp;
                start = end + 1;
            }
        }
        mem_free(page->url);
        mem_free(page->content);
        mem_free(page);
        unbounded_buffer_done(in_args->page_queue);
        mutex_lock(in_args->done_mutex);
        cond_signal(in_args->done_cond);
        mutex_unlock(in_args->done_mutex);
    }
    return NULL;
}
예제 #11
0
파일: dlg.c 프로젝트: AndreyRybkin/kamailio
/*
 * UAS side - update a dialog from a request
 */
int dlg_request_uas(dlg_t* _d, struct sip_msg* _m, target_refresh_t is_target_refresh)
{
	str contact;
	int cseq;

	if (!_d || !_m) {
		LOG(L_ERR, "dlg_request_uas(): Invalid parameter value\n");
		return -1;
	}

	     /* We must check if the request is not out of order or retransmission
	      * first, if so then we will not update anything
	      */
	if (parse_headers(_m, HDR_CSEQ_F, 0) == -1) {
		LOG(L_ERR, "dlg_request_uas(): Error while parsing headers\n");
		return -2;
	}
	if (get_cseq_value(_m, (unsigned int*)&cseq) < 0) return -3;
	if (_d->rem_seq.is_set && (cseq <= _d->rem_seq.value)) return 0;

	     /* Neither out of order nor retransmission -> update */
	_d->rem_seq.value = cseq;
	_d->rem_seq.is_set = 1;
	
	     /* We will als update remote target URI if the message 
	      * is target refresher
	      */
	if (refresh_dialog_req(_m, is_target_refresh)) { /* target refresher */
		if (parse_headers(_m, HDR_CONTACT_F, 0) == -1) {
			LOG(L_ERR, "dlg_request_uas(): Error while parsing headers\n");
			return -4;
		}
		
		if (get_contact_uri(_m, &contact) < 0) return -5;
		if (contact.len) {
			if (_d->rem_target.s) shm_free(_d->rem_target.s);
			if (_d->dst_uri.s) {
				shm_free(_d->dst_uri.s);
				_d->dst_uri.s = 0;
				_d->dst_uri.len = 0;
			}
			if (str_duplicate(&_d->rem_target, &contact) < 0) return -6;
		}

		if (calculate_hooks(_d) < 0)
			return -1;
		
	}

	return 0;
}
예제 #12
0
파일: strings.c 프로젝트: Essency/services
BOOL str_creationinfo_set(CreationInfo *info, CSTR creator, CSTR reason, time_t time_set) {

	if (IS_NULL(info) || IS_NULL(creator) || IS_NULL(reason))
		return FALSE;

	str_creator_set(&(info->creator), creator, time_set);

	if (IS_NOT_NULL(info->reason))
		mem_free(info->reason);

	info->reason = str_duplicate(reason);

	return TRUE;
}
예제 #13
0
void hashset_insert(hashset_t *h, char *str) {
    size_t bucket = hashset_hash(str) % h->buckets;
    mutex_lock(&h->mutexes[bucket]);
    node_t *node = h->heads[bucket];
    while (node != NULL) {
        if (strcmp((char *)node->ptr, str) == 0)
            break;
        node = node->next;
    }
    if (node == NULL) {
        node = (node_t *)mem_malloc(sizeof(node_t));
        node->ptr = (void *)str_duplicate(str);
        node->next = h->heads[bucket];
        h->heads[bucket] = node;
    }
    mutex_unlock(&h->mutexes[bucket]);
}
예제 #14
0
파일: strings.c 프로젝트: Essency/services
BOOL str_creator_set(Creator *creator, CSTR name, time_t time_set) {

	if (IS_NOT_NULL(creator)) {

		if (IS_NOT_NULL(name)) {

			if (IS_NOT_NULL(creator->name))
				mem_free(creator->name);

			creator->name = str_duplicate(name);
		}

		creator->time = time_set != 0 ? time_set : NOW;
		return TRUE;
	
	} else
		return FALSE;
}
예제 #15
0
파일: dlg.c 프로젝트: AndreyRybkin/kamailio
/*
 * UAS side - update dialog state and to tag
 */
int update_dlg_uas(dlg_t *_d, int _code, str* _tag)
{
	if (_d->state == DLG_CONFIRMED) {
		LOG(L_ERR, "update_dlg_uas(): Dialog is already confirmed\n");
		return -1;
	} else if (_d->state == DLG_DESTROYED) {
		LOG(L_ERR, "update_dlg_uas(): Dialog is already destroyed\n");
		return -2;
	}

	if (_tag && _tag->s) {
		if (_d->id.loc_tag.s) {
			if ((_tag->len == _d->id.loc_tag.len)
			&& (!memcmp(_tag->s, _d->id.loc_tag.s, _tag->len))) {
				LOG(L_DBG, "update_dlg_uas(): Local tag is already set\n");
			} else {
				LOG(L_ERR, "update_dlg_uas(): ERROR: trying to rewrite local tag\n");
				return -3;
			}
		} else {
			if (str_duplicate(&_d->id.loc_tag, _tag) < 0) {
				LOG(L_ERR, "update_dlg_uas(): Not enough memory\n");
				return -4;
			}
		}
	}

	if ((100 < _code) && (_code < 200))
		_d->state = DLG_EARLY;
	else if (_code < 300)
		_d->state = DLG_CONFIRMED;
	else
		_d->state = DLG_DESTROYED;

	return 0;
}
예제 #16
0
int crawl(char *start_url, int download_workers, int parse_workers, int queue_size,
    char *(*_fetch_fn)(char *url), void (*_edge_fn)(char *from, char *to)) {
    int i;

    bounded_buffer_t url_queue;
    unbounded_buffer_t page_queue;
    hashset_t url_set;
    bounded_buffer_init(&url_queue, queue_size);
    unbounded_buffer_init(&page_queue);
    hashset_init(&url_set, HASHSET_BUCKETS);

    bounded_buffer_put(&url_queue, (void *)str_duplicate(start_url));

    mutex_t done_mutex;
    cond_t done_cond;

    mutex_init(&done_mutex);
    cond_init(&done_cond);

    struct input_args in_args;
    in_args.url_queue = &url_queue;
    in_args.page_queue = &page_queue;
    in_args.url_set = &url_set;
    in_args.fetch = _fetch_fn;
    in_args.edge = _edge_fn;
    in_args.done_mutex = &done_mutex;
    in_args.done_cond = &done_cond;

    thread_t downloaders[download_workers];
    thread_t parsers[parse_workers];
    for (i = 0; i < download_workers; i++)
        thread_create(&downloaders[i], downloader, (void *)&in_args);
    for (i = 0; i < parse_workers; i++)
        thread_create(&parsers[i], parser, (void *)&in_args);

    while (1) {
        mutex_lock(&done_mutex);
        mutex_lock(&url_queue.mutex);
        mutex_lock(&url_queue.worker_mutex);
        mutex_lock(&page_queue.mutex);
        mutex_lock(&page_queue.worker_mutex);
        if (url_queue.count == 0 && url_queue.workers == 0 &&
            page_queue.count == 0 && page_queue.workers == 0) {
            url_queue.done = 1;
            page_queue.done = 1;
            cond_broadcast(&url_queue.empty);
            cond_broadcast(&url_queue.fill);
            cond_broadcast(&page_queue.fill);
            mutex_unlock(&url_queue.mutex);
            mutex_unlock(&url_queue.worker_mutex);
            mutex_unlock(&page_queue.mutex);
            mutex_unlock(&page_queue.worker_mutex);
            mutex_unlock(&done_mutex);
            break;
        } else {
            mutex_unlock(&url_queue.mutex);
            mutex_unlock(&url_queue.worker_mutex);
            mutex_unlock(&page_queue.mutex);
            mutex_unlock(&page_queue.worker_mutex);
            cond_wait(&done_cond, &done_mutex);
            mutex_unlock(&done_mutex);
        }
    }

    for (i = 0; i < download_workers; i++)
        thread_join(downloaders[i], NULL);
    for (i = 0; i < parse_workers; i++)
        thread_join(parsers[i], NULL);

    bounded_buffer_destroy(&url_queue);
    unbounded_buffer_destroy(&page_queue);
    hashset_destroy(&url_set);

    return 0;
}
예제 #17
0
/* inserts a callid item to table, and removes the least item if the table is full */
int proc_cid(ttable *ptable,
			 str *scid,
			 str *sftag,
			 unsigned int ucseq,
			 time_t ivalidbefore)
{
	tcid_item *pshmcid, *pcid_item;
	tdlg_item *pshmdlg, *pdlg_item, *pdlg_item_prev;
	unsigned int uhash;

	/* we suppose that this SIP request is not replayed so it doesn't exist in
	   the table so we prepare to insert */
	if (!(pshmdlg=(tdlg_item *)shm_malloc(sizeof(*pshmdlg)))) {
		LOG(L_ERR, "AUTH_IDENTITY:addcid2table: No enough shared memory\n");
		return -1;
	}
	memset(pshmdlg, 0, sizeof(*pshmdlg));
	if (str_duplicate(&pshmdlg->sftag, sftag))
		return -2;
	pshmdlg->ucseq=ucseq;


	/* we're looking for this call-id item if exists */
	uhash=get_hash1_raw(scid->s, scid->len) & (CALLID_TABLE_ENTRIES-1);

	lock_element(&ptable->entries[uhash]);

	pcid_item = search_item_in_table_unsafe(ptable,
											(const void *)scid, /* Call-id is the key */
											uhash);
	/* we've found one call-id so we're looking for the required SIP request */
	if (pcid_item) {
		for (pdlg_item=pcid_item->pdlgs, pdlg_item_prev=NULL;
		     pdlg_item;
			 pdlg_item=pdlg_item->pnext) {
			if (pdlg_item->sftag.len==sftag->len
				&& !memcmp(pdlg_item->sftag.s, sftag->s, sftag->len)) {
				/* we found this call with this from tag */
				if (pdlg_item->ucseq>=ucseq) {
					/* we've found this or older request in the table!
					   this call is replayed! */
					release_element(&ptable->entries[uhash]);

					shm_free(pshmdlg->sftag.s);
					shm_free(pshmdlg);
					return AUTH_FOUND;
				} else {
					/* this is another later request whithin this dialog so we
					   update the saved cseq */
					pdlg_item->ucseq=ucseq;
					release_element(&ptable->entries[uhash]);

					shm_free(pshmdlg->sftag.s);
					shm_free(pshmdlg);
					return 0;
				}
			}
			/* we save the previous dialog item in order to append a new item more easily */
			pdlg_item_prev ?
				(pdlg_item_prev=pdlg_item_prev->pnext) :
				(pdlg_item_prev=pdlg_item);
		}
		/* we append this to item dialogs*/
		pdlg_item_prev->pnext=pshmdlg;
		/* this is the latest request; we hold all request concerned this
		   call-id until the latest request is valid */
		pcid_item->ivalidbefore=ivalidbefore;
	}

	release_element(&ptable->entries[uhash]);

	if (!pcid_item) {
		/* this is the first request with this call-id */
		if (!(pshmcid=(tcid_item *)shm_malloc(sizeof(*pshmcid)))) {
			LOG(L_ERR, "AUTH_IDENTITY:addcid2table: No enough shared memory\n");
			return -4;
		}
		memset(pshmcid, 0, sizeof(*pshmcid));
		if (str_duplicate(&pshmcid->scid, scid)) {
			return -5;
		}
		pshmcid->ivalidbefore=ivalidbefore;
		pshmcid->pdlgs=pshmdlg;
		if (insert_into_table(ptable, (void*)pshmcid, uhash))
			return -6;
	}

	return 0;
}