]> sjero.net Git - linphone/blob - linphone/oRTP/src/str_utils.c
a38620b303736edcbf02f4323850f6dcb39380cb
[linphone] / linphone / oRTP / src / str_utils.c
1 /*
2   The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack.
3   Copyright (C) 2001  Simon MORLAT simon.morlat@linphone.org
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 "ortp/ortp.h"
21 #include "ortp/rtp.h"
22 #include "ortp/str_utils.h"
23 #include "utils.h"
24
25 void qinit(queue_t *q){
26         mblk_init(&q->_q_stopper);
27         q->_q_stopper.b_next=&q->_q_stopper;
28         q->_q_stopper.b_prev=&q->_q_stopper;
29         q->q_mcount=0;
30 }
31
32 void mblk_init(mblk_t *mp)
33 {
34         mp->b_cont=mp->b_prev=mp->b_next=NULL;
35         mp->b_rptr=mp->b_wptr=NULL;
36         mp->reserved1=0;
37         mp->reserved2=0;
38 }
39
40 dblk_t *datab_alloc(int size){
41         dblk_t *db;
42         int total_size=sizeof(dblk_t)+size;
43         db=(dblk_t *) ortp_malloc(total_size);
44         db->db_base=(uint8_t*)db+sizeof(dblk_t);
45         db->db_lim=db->db_base+size;
46         db->db_ref=1;
47         db->db_freefn=NULL;     /* the buffer pointed by db_base must never be freed !*/
48         return db;
49 }
50
51 static inline void datab_ref(dblk_t *d){
52         d->db_ref++;
53 }
54
55 static inline void datab_unref(dblk_t *d){
56         d->db_ref--;
57         if (d->db_ref==0){
58                 if (d->db_freefn!=NULL)
59                         d->db_freefn(d->db_base);
60                 ortp_free(d);
61         }
62 }
63
64
65 mblk_t *allocb(int size, int pri)
66 {
67         mblk_t *mp;
68         dblk_t *datab;
69         
70         mp=(mblk_t *) ortp_malloc(sizeof(mblk_t));
71         mblk_init(mp);
72         datab=datab_alloc(size);
73         
74         mp->b_datap=datab;
75         mp->b_rptr=mp->b_wptr=datab->db_base;
76         mp->b_next=mp->b_prev=mp->b_cont=NULL;
77         return mp;
78 }
79
80 mblk_t *esballoc(uint8_t *buf, int size, int pri, void (*freefn)(void*) )
81 {
82         mblk_t *mp;
83         dblk_t *datab;
84         
85         mp=(mblk_t *) ortp_malloc(sizeof(mblk_t));
86         mblk_init(mp);
87         datab=(dblk_t *) ortp_malloc(sizeof(dblk_t));
88         
89
90         datab->db_base=buf;
91         datab->db_lim=buf+size;
92         datab->db_ref=1;
93         datab->db_freefn=freefn;
94         
95         mp->b_datap=datab;
96         mp->b_rptr=mp->b_wptr=buf;
97         mp->b_next=mp->b_prev=mp->b_cont=NULL;
98         return mp;
99 }
100
101         
102 void freeb(mblk_t *mp)
103 {
104         return_if_fail(mp->b_datap!=NULL);
105         return_if_fail(mp->b_datap->db_base!=NULL);
106         
107         datab_unref(mp->b_datap);
108         ortp_free(mp);
109 }
110
111 void freemsg(mblk_t *mp)
112 {
113         mblk_t *tmp1,*tmp2;
114         tmp1=mp;
115         while(tmp1!=NULL)
116         {
117                 tmp2=tmp1->b_cont;
118                 freeb(tmp1);
119                 tmp1=tmp2;
120         }
121 }
122
123 mblk_t *dupb(mblk_t *mp)
124 {
125         mblk_t *newm;
126         return_val_if_fail(mp->b_datap!=NULL,NULL);
127         return_val_if_fail(mp->b_datap->db_base!=NULL,NULL);
128         
129         datab_ref(mp->b_datap);
130         newm=(mblk_t *) ortp_malloc(sizeof(mblk_t));
131         mblk_init(newm);
132         newm->reserved1=mp->reserved1;
133         newm->reserved2=mp->reserved2;
134         newm->b_datap=mp->b_datap;
135         newm->b_rptr=mp->b_rptr;
136         newm->b_wptr=mp->b_wptr;
137         return newm;
138 }
139
140 /* duplicates a complex mblk_t */
141 mblk_t  *dupmsg(mblk_t* m)
142 {
143         mblk_t *newm=NULL,*mp,*prev;
144         prev=newm=dupb(m);
145         m=m->b_cont;
146         while (m!=NULL){
147                 mp=dupb(m);
148                 prev->b_cont=mp;
149                 prev=mp;
150                 m=m->b_cont;
151         }
152         return newm;
153 }
154
155 void putq(queue_t *q,mblk_t *mp)
156 {
157         q->_q_stopper.b_prev->b_next=mp;
158         mp->b_prev=q->_q_stopper.b_prev;
159         mp->b_next=&q->_q_stopper;
160         q->_q_stopper.b_prev=mp;
161         q->q_mcount++;
162 }
163
164 mblk_t *getq(queue_t *q)
165 {
166         mblk_t *tmp;
167         tmp=q->_q_stopper.b_next;
168         if (tmp==&q->_q_stopper) return NULL;
169         q->_q_stopper.b_next=tmp->b_next;
170         tmp->b_next->b_prev=&q->_q_stopper;
171         tmp->b_prev=NULL;
172         tmp->b_next=NULL;
173         q->q_mcount--;
174         return tmp;
175 }
176
177 mblk_t * peekq(queue_t *q){
178         mblk_t *tmp;
179         tmp=q->_q_stopper.b_next;
180         if (tmp==&q->_q_stopper) return NULL;
181         return tmp;
182 }
183
184 /* insert mp in q just before emp */
185 void insq(queue_t *q,mblk_t *emp, mblk_t *mp)
186 {
187         if (emp==NULL){
188                 putq(q,mp);
189                 return;
190         }
191         q->q_mcount++;
192         emp->b_prev->b_next=mp;
193         mp->b_prev=emp->b_prev;
194         emp->b_prev=mp;
195         mp->b_next=emp; 
196 }
197
198 void remq(queue_t *q, mblk_t *mp){
199         q->q_mcount--;
200         mp->b_prev->b_next=mp->b_next;
201         mp->b_next->b_prev=mp->b_prev;
202         mp->b_next=NULL;
203         mp->b_prev=NULL;
204 }
205
206 /* remove and free all messages in the q */
207 void flushq(queue_t *q, int how)
208 {
209         mblk_t *mp;
210         
211         while ((mp=getq(q))!=NULL)
212         {
213                 freemsg(mp);
214         }
215 }
216
217 int msgdsize(const mblk_t *mp)
218 {
219         int msgsize=0;
220         while(mp!=NULL){
221                 msgsize+=(int) (mp->b_wptr-mp->b_rptr);
222                 mp=mp->b_cont;
223         }
224         return msgsize;
225 }
226
227 void msgpullup(mblk_t *mp,int len)
228 {
229         mblk_t *firstm=mp;
230         dblk_t *db;
231         int wlen=0;
232
233         if (mp->b_cont==NULL && len==-1) return;        /*nothing to do, message is not fragmented */
234
235         if (len==-1) len=msgdsize(mp);
236         db=datab_alloc(len);
237         while(wlen<len && mp!=NULL){
238                 int remain=len-wlen;
239                 int mlen=mp->b_wptr-mp->b_rptr;
240                 if (mlen<=remain){
241                         memcpy(&db->db_base[wlen],mp->b_rptr,mlen);
242                         wlen+=mlen;
243                         mp=mp->b_cont;
244                 }else{
245                         memcpy(&db->db_base[wlen],mp->b_rptr,remain);
246                         wlen+=remain;
247                 }
248         }
249         /*set firstm to point to the new datab */
250         freemsg(firstm->b_cont);
251         firstm->b_cont=NULL;
252         datab_unref(firstm->b_datap);
253         firstm->b_datap=db;
254         firstm->b_rptr=db->db_base;
255         firstm->b_wptr=firstm->b_rptr+wlen;
256 }
257
258
259 mblk_t *copyb(mblk_t *mp)
260 {
261         mblk_t *newm;
262         int len=(int) (mp->b_wptr-mp->b_rptr);
263         newm=allocb(len,BPRI_MED);
264         memcpy(newm->b_wptr,mp->b_rptr,len);
265         newm->b_wptr+=len;
266         return newm;
267 }
268
269 mblk_t *copymsg(mblk_t *mp)
270 {
271         mblk_t *newm=0,*m;
272         m=newm=copyb(mp);
273         mp=mp->b_cont;
274         while(mp!=NULL){
275                 m->b_cont=copyb(mp);
276                 m=m->b_cont;
277                 mp=mp->b_cont;
278         }
279         return newm;
280 }
281
282 mblk_t * appendb(mblk_t *mp, const char *data, int size, bool_t pad){
283         int padcnt=0;
284         int i;
285         if (pad){
286                 padcnt= (int)(4L-( (long)(((long)mp->b_wptr)+size) % 4L)) % 4L;
287         }
288         if ((mp->b_wptr + size +padcnt) > mp->b_datap->db_lim){
289                 /* buffer is not large enough: append a new block (with the same size ?)*/
290                 int plen=(int)((char*)mp->b_datap->db_lim - (char*) mp->b_datap->db_base);
291                 mp->b_cont=allocb(MAX(plen,size),0);
292                 mp=mp->b_cont;
293         }
294         if (size) memcpy(mp->b_wptr,data,size);
295         mp->b_wptr+=size;
296         for (i=0;i<padcnt;i++){
297                 mp->b_wptr[0]=0;
298                 mp->b_wptr++;
299         }
300         return mp;
301 }
302
303 void msgappend(mblk_t *mp, const char *data, int size, bool_t pad){
304         while(mp->b_cont!=NULL) mp=mp->b_cont;
305         appendb(mp,data,size,pad);
306 }
307
308 mblk_t *concatb(mblk_t *mp, mblk_t *newm){
309         while (mp->b_cont!=NULL) mp=mp->b_cont;
310         mp->b_cont=newm;
311         while(newm->b_cont!=NULL) newm=newm->b_cont;
312         return newm;
313 }
314
315 void msgb_allocator_init(msgb_allocator_t *a){
316         qinit(&a->q);
317 }
318
319 mblk_t *msgb_allocator_alloc(msgb_allocator_t *a, int size){
320         queue_t *q=&a->q;
321         mblk_t *m,*found=NULL;
322
323         /*lookup for an unused msgb (data block with ref count ==1)*/
324         for(m=qbegin(q);!qend(q,m);m=qnext(q,m)){
325                 if (m->b_datap->db_ref==1 && m->b_datap->db_lim-m->b_datap->db_base>=size){
326                         found=m;
327                         break;
328                 }
329         }
330         if (found==NULL){
331                 found=allocb(size,0);
332                 putq(q,found);
333         }
334         return dupb(found);
335 }
336
337 void msgb_allocator_uninit(msgb_allocator_t *a){
338         flushq(&a->q,-1);
339 }