1 /*
2   The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3   Copyright (C) 2001-2020 Aymeric MOIZARD amoizard@antisip.com
4 
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9 
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14 
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 #include <osip2/internal.h>
21 
22 #include <osipparser2/osip_port.h>
23 #include <osip2/osip_fifo.h>
24 
25 /* always use this method to initiate osip_fifo_t.
26  */
osip_fifo_init(osip_fifo_t * ff)27 void osip_fifo_init(osip_fifo_t *ff) {
28 #ifndef OSIP_MONOTHREAD
29   ff->qislocked = osip_mutex_init();
30   /*INIT SEMA TO BLOCK ON GET() WHEN QUEUE IS EMPTY */
31   ff->qisempty = osip_sem_init(0);
32 #endif
33   osip_list_init(&ff->queue);
34   /* ff->nb_elt = 0; */
35   ff->state = osip_empty;
36 }
37 
osip_fifo_add(osip_fifo_t * ff,void * el)38 int osip_fifo_add(osip_fifo_t *ff, void *el) {
39 #ifndef OSIP_MONOTHREAD
40   osip_mutex_lock(ff->qislocked);
41 #endif
42 
43   osip_list_add(&ff->queue, el, -1); /* insert at end of queue */
44   ff->state = osip_ok;
45 
46 #ifndef OSIP_MONOTHREAD
47   osip_sem_post(ff->qisempty);
48   osip_mutex_unlock(ff->qislocked);
49 #endif
50   return OSIP_SUCCESS;
51 }
52 
osip_fifo_insert(osip_fifo_t * ff,void * el)53 int osip_fifo_insert(osip_fifo_t *ff, void *el) {
54 #ifndef OSIP_MONOTHREAD
55   osip_mutex_lock(ff->qislocked);
56 #endif
57 
58   osip_list_add(&ff->queue, el, 0); /* insert at end of queue */
59   ff->state = osip_ok;
60 
61 #ifndef OSIP_MONOTHREAD
62   osip_sem_post(ff->qisempty);
63   osip_mutex_unlock(ff->qislocked);
64 #endif
65   return OSIP_SUCCESS;
66 }
67 
osip_fifo_size(osip_fifo_t * ff)68 int osip_fifo_size(osip_fifo_t *ff) {
69   int i;
70 
71 #ifndef OSIP_MONOTHREAD
72   osip_mutex_lock(ff->qislocked);
73 #endif
74 
75   i = osip_list_size(&ff->queue);
76 #ifndef OSIP_MONOTHREAD
77   osip_mutex_unlock(ff->qislocked);
78 #endif
79   return i;
80 }
81 
osip_fifo_get(osip_fifo_t * ff)82 void *osip_fifo_get(osip_fifo_t *ff) {
83   void *el = NULL;
84 
85 #ifndef OSIP_MONOTHREAD
86   int i = osip_sem_wait(ff->qisempty);
87 
88   if (i != 0)
89     return NULL;
90 
91   osip_mutex_lock(ff->qislocked);
92 #endif
93 
94   if (ff->state != osip_empty) {
95     el = osip_list_get(&ff->queue, 0);
96     osip_list_remove(&ff->queue, 0);
97     /* ff->nb_elt--; */
98 
99   } else {
100     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "no element in fifo.\n"));
101 #ifndef OSIP_MONOTHREAD
102     osip_mutex_unlock(ff->qislocked);
103 #endif
104     return OSIP_SUCCESS; /* pile vide */
105   }
106 
107   /* if (ff->nb_elt <= 0) */
108   if (osip_list_size(&ff->queue) <= 0)
109     ff->state = osip_empty;
110 
111   else
112     ff->state = osip_ok;
113 
114 #ifndef OSIP_MONOTHREAD
115   osip_mutex_unlock(ff->qislocked);
116 #endif
117   return el;
118 }
119 
osip_fifo_tryget(osip_fifo_t * ff)120 void *osip_fifo_tryget(osip_fifo_t *ff) {
121   void *el = NULL;
122 
123 #ifndef OSIP_MONOTHREAD
124 
125   if (0 != osip_sem_trywait(ff->qisempty)) { /* no elements... */
126     return NULL;
127   }
128 
129   osip_mutex_lock(ff->qislocked);
130 #else
131 
132   if (ff->state == osip_empty)
133     return NULL;
134 
135 #endif
136 
137   if (ff->state != osip_empty) {
138     el = osip_list_get(&ff->queue, 0);
139     osip_list_remove(&ff->queue, 0);
140     /* ff->nb_elt--; */
141   }
142 
143 #ifndef OSIP_MONOTHREAD
144 
145   else { /* this case MUST never happen... */
146     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO4, NULL, "no element in fifo.\n"));
147     osip_mutex_unlock(ff->qislocked);
148     return OSIP_SUCCESS;
149   }
150 
151 #endif
152 
153   /* if (ff->nb_elt <= 0) */
154   if (osip_list_size(&ff->queue) <= 0)
155     ff->state = osip_empty;
156 
157   else
158     ff->state = osip_ok;
159 
160 #ifndef OSIP_MONOTHREAD
161   osip_mutex_unlock(ff->qislocked);
162 #endif
163   return el;
164 }
165 
osip_fifo_free(osip_fifo_t * ff)166 void osip_fifo_free(osip_fifo_t *ff) {
167   if (ff == NULL)
168     return;
169 
170 #ifndef OSIP_MONOTHREAD
171   osip_mutex_destroy(ff->qislocked);
172   /* seems that pthread_mutex_destroy does not free space by itself */
173   osip_sem_destroy(ff->qisempty);
174 #endif
175   osip_free(ff);
176 }
177