/** * $Id$ * * MSILO module * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of Kamailio, a free SIP server. * * Kamailio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * Kamailio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * History: * -------- * 2003-03-11 major locking changes: not it uses locking.h (andrei) */ #include <string.h> #include <unistd.h> #include <stdio.h> #include "../../mem/mem.h" #include "../../mem/shm_mem.h" #include "../../dprint.h" #include "ms_msg_list.h" /** * create a new element */ msg_list_el msg_list_el_new(void) { msg_list_el mle = NULL; mle = (msg_list_el)shm_malloc(sizeof(t_msg_list_el)); if(mle == NULL) return NULL; mle->next = NULL; mle->prev = NULL; mle->msgid = 0; mle->flag = MS_MSG_NULL; return mle; } /** * free an element */ void msg_list_el_free(msg_list_el mle) { if(mle) shm_free(mle); } /** * free a list of elements */ void msg_list_el_free_all(msg_list_el mle) { msg_list_el p0, p1; if(!mle) return; p0 = mle; while(p0) { p1 = p0; p0 = p0->next; msg_list_el_free(p1); } } /** * init a list */ msg_list msg_list_init(void) { msg_list ml = NULL; ml = (msg_list)shm_malloc(sizeof(t_msg_list)); if(ml == NULL) return NULL; /* init locks */ if (lock_init(&ml->sem_sent)==0){ LM_CRIT("could not initialize a lock\n"); goto clean; }; if (lock_init(&ml->sem_done)==0){ LM_CRIT("could not initialize a lock\n"); lock_destroy(&ml->sem_sent); goto clean; }; ml->nrsent = 0; ml->nrdone = 0; ml->lsent = NULL; ml->ldone = NULL; return ml; clean: shm_free(ml); return NULL; } /** * free a list */ void msg_list_free(msg_list ml) { msg_list_el p0, p1; if(!ml) return; lock_destroy(&ml->sem_sent); lock_destroy(&ml->sem_done); if(ml->nrsent>0 && ml->lsent) { // free sent list p0 = ml->lsent; ml->lsent = NULL; ml->nrsent = 0; while(p0) { p1 = p0->next; msg_list_el_free(p0); p0 = p1; } } if(ml->nrdone>0 && ml->ldone) { // free done list p0 = ml->ldone; ml->ldone = NULL; ml->nrdone = 0; while(p0) { p1 = p0->next; msg_list_el_free(p0); p0 = p1; } } shm_free(ml); } /** * check if a message is in list */ int msg_list_check_msg(msg_list ml, int mid) { msg_list_el p0, p1; if(!ml || mid==0) goto errorx; LM_DBG("checking msgid=%d\n", mid); lock_get(&ml->sem_sent); p0 = p1 = ml->lsent; while(p0) { if(p0->msgid==mid) goto exist; p1 = p0; p0 = p0->next; } p0 = msg_list_el_new(); if(!p0) { LM_ERR("failed to create new msg elem.\n"); goto error; } p0->msgid = mid; p0->flag |= MS_MSG_SENT; if(p1) { p1->next = p0; p0->prev = p1; goto done; } ml->lsent = p0; done: ml->nrsent++; lock_release(&ml->sem_sent); LM_DBG("msg added to sent list.\n"); return MSG_LIST_OK; exist: lock_release(&ml->sem_sent); LM_DBG("msg already in sent list.\n"); return MSG_LIST_EXIST; error: lock_release(&ml->sem_sent); errorx: return MSG_LIST_ERR; } /** * set flag for message with mid */ int msg_list_set_flag(msg_list ml, int mid, int fl) { msg_list_el p0; if(ml==0 || mid==0) { LM_ERR("bad param %p / %d\n", ml, fl); goto errorx; } lock_get(&ml->sem_sent); p0 = ml->lsent; while(p0) { if(p0->msgid==mid) { p0->flag |= fl; LM_DBG("mid:%d fl:%d\n", p0->msgid, fl); goto done; } p0 = p0->next; } done: lock_release(&ml->sem_sent); return MSG_LIST_OK; errorx: return MSG_LIST_ERR; } /** * check if the messages from list were sent */ int msg_list_check(msg_list ml) { msg_list_el p0; msg_list_el p1; if(!ml) goto errorx; lock_get(&ml->sem_sent); if(ml->nrsent<=0) goto done; lock_get(&ml->sem_done); p0 = ml->lsent; while(p0) { p1 = p0->next; if(p0->flag & MS_MSG_DONE || p0->flag & MS_MSG_ERRO) { LM_DBG("mid:%d got reply\n", p0->msgid); if(p0->prev) (p0->prev)->next = p0->next; else ml->lsent = p0->next; if(p0->next) (p0->next)->prev = p0->prev; ml->nrsent--; if(!ml->nrsent) ml->lsent = NULL; if(ml->ldone) (ml->ldone)->prev = p0; p0->next = ml->ldone; p0->prev = NULL; ml->ldone = p0; ml->nrdone++; } p0 = p1; } lock_release(&ml->sem_done); done: lock_release(&ml->sem_sent); return MSG_LIST_OK; errorx: return MSG_LIST_ERR; } /** * reset a list * return old list */ msg_list_el msg_list_reset(msg_list ml) { msg_list_el p0; if(!ml) return NULL; lock_get(&ml->sem_done); p0 = ml->ldone; ml->ldone = NULL; ml->nrdone = 0; lock_release(&ml->sem_done); return p0; }