Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / libosip2 / src / osipparser2 / sdp_message.c
1 /*
2   The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3   Copyright (C) 2001,2002,2003  Aymeric MOIZARD jack@atosc.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 <osipparser2/osip_const.h>
21 #include <osipparser2/sdp_message.h>
22 #include <osipparser2/osip_port.h>
23
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #define ERR_ERROR   -1          /* bad header */
28 #define ERR_DISCARD  0          /* wrong header */
29 #define WF           1          /* well formed header */
30
31 static int sdp_message_parse_v (sdp_message_t * sdp, char *buf, char **next);
32 static int sdp_message_parse_o (sdp_message_t * sdp, char *buf, char **next);
33 static int sdp_message_parse_s (sdp_message_t * sdp, char *buf, char **next);
34 static int sdp_message_parse_i (sdp_message_t * sdp, char *buf, char **next);
35 static int sdp_message_parse_u (sdp_message_t * sdp, char *buf, char **next);
36 static int sdp_message_parse_e (sdp_message_t * sdp, char *buf, char **next);
37 static int sdp_message_parse_p (sdp_message_t * sdp, char *buf, char **next);
38 static int sdp_message_parse_c (sdp_message_t * sdp, char *buf, char **next);
39 static int sdp_message_parse_b (sdp_message_t * sdp, char *buf, char **next);
40 static int sdp_message_parse_t (sdp_message_t * sdp, char *buf, char **next);
41 static int sdp_message_parse_r (sdp_message_t * sdp, char *buf, char **next);
42 static int sdp_message_parse_z (sdp_message_t * sdp, char *buf, char **next);
43 static int sdp_message_parse_k (sdp_message_t * sdp, char *buf, char **next);
44 static int sdp_message_parse_a (sdp_message_t * sdp, char *buf, char **next);
45 static int sdp_message_parse_m (sdp_message_t * sdp, char *buf, char **next);
46
47 static int sdp_append_media (char *string, int size, char *tmp,
48                              sdp_media_t * media, char **next_tmp);
49 static int sdp_append_attribute (char *string, int size, char *tmp,
50                                  sdp_attribute_t * attribute,
51                                  char **next_tmp);
52 static int sdp_append_key (char *string, int size, char *tmp, sdp_key_t * key,
53                            char **next_tmp);
54 static int sdp_append_time_descr (char *string, int size, char *tmp,
55                                   sdp_time_descr_t * time_descr,
56                                   char **next_tmp);
57 static int sdp_append_bandwidth (char *string, int size, char *tmp,
58                                  sdp_bandwidth_t * bandwidth,
59                                  char **next_tmp);
60 static int sdp_append_connection (char *string, int size, char *tmp,
61                                   sdp_connection_t * conn, char **next_tmp);
62
63 int
64 sdp_bandwidth_init (sdp_bandwidth_t ** b)
65 {
66   *b = (sdp_bandwidth_t *) osip_malloc (sizeof (sdp_bandwidth_t));
67   if (*b == NULL)
68     return -1;
69   (*b)->b_bwtype = NULL;
70   (*b)->b_bandwidth = NULL;
71   return 0;
72 }
73
74 void
75 sdp_bandwidth_free (sdp_bandwidth_t * b)
76 {
77   if (b == NULL)
78     return;
79   osip_free (b->b_bwtype);
80   osip_free (b->b_bandwidth);
81   osip_free (b);
82 }
83
84 int
85 sdp_time_descr_init (sdp_time_descr_t ** td)
86 {
87   *td = (sdp_time_descr_t *) osip_malloc (sizeof (sdp_time_descr_t));
88   if (*td == NULL)
89     return -1;
90   (*td)->t_start_time = NULL;
91   (*td)->t_stop_time = NULL;
92   (*td)->r_repeats = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
93   osip_list_init ((*td)->r_repeats);
94   return 0;
95 }
96
97 void
98 sdp_time_descr_free (sdp_time_descr_t * td)
99 {
100   if (td == NULL)
101     return;
102   osip_free (td->t_start_time);
103   osip_free (td->t_stop_time);
104   osip_list_ofchar_free (td->r_repeats);
105   osip_free (td);
106 }
107
108 int
109 sdp_key_init (sdp_key_t ** key)
110 {
111   *key = (sdp_key_t *) osip_malloc (sizeof (sdp_key_t));
112   if (*key == NULL)
113     return -1;
114   (*key)->k_keytype = NULL;
115   (*key)->k_keydata = NULL;
116   return 0;
117 }
118
119 void
120 sdp_key_free (sdp_key_t * key)
121 {
122   if (key == NULL)
123     return;
124   osip_free (key->k_keytype);
125   osip_free (key->k_keydata);
126   osip_free (key);
127 }
128
129 int
130 sdp_attribute_init (sdp_attribute_t ** attribute)
131 {
132   *attribute = (sdp_attribute_t *) osip_malloc (sizeof (sdp_attribute_t));
133   if (*attribute == NULL)
134     return -1;
135   (*attribute)->a_att_field = NULL;
136   (*attribute)->a_att_value = NULL;
137   return 0;
138 }
139
140 void
141 sdp_attribute_free (sdp_attribute_t * attribute)
142 {
143   if (attribute == NULL)
144     return;
145   osip_free (attribute->a_att_field);
146   osip_free (attribute->a_att_value);
147   osip_free (attribute);
148 }
149
150 int
151 sdp_connection_init (sdp_connection_t ** connection)
152 {
153   *connection = (sdp_connection_t *) osip_malloc (sizeof (sdp_connection_t));
154   if (*connection == NULL)
155     return -1;
156   (*connection)->c_nettype = NULL;
157   (*connection)->c_addrtype = NULL;
158   (*connection)->c_addr = NULL;
159   (*connection)->c_addr_multicast_ttl = NULL;
160   (*connection)->c_addr_multicast_int = NULL;
161   return 0;
162 }
163
164 void
165 sdp_connection_free (sdp_connection_t * connection)
166 {
167   if (connection == NULL)
168     return;
169   osip_free (connection->c_nettype);
170   osip_free (connection->c_addrtype);
171   osip_free (connection->c_addr);
172   osip_free (connection->c_addr_multicast_ttl);
173   osip_free (connection->c_addr_multicast_int);
174   osip_free (connection);
175 }
176
177 int
178 sdp_media_init (sdp_media_t ** media)
179 {
180   *media = (sdp_media_t *) osip_malloc (sizeof (sdp_media_t));
181   if (*media == NULL)
182     return -1;
183   (*media)->m_media = NULL;
184   (*media)->m_port = NULL;
185   (*media)->m_number_of_port = NULL;
186   (*media)->m_proto = NULL;
187   (*media)->m_payloads = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
188   osip_list_init ((*media)->m_payloads);
189   (*media)->i_info = NULL;
190   (*media)->c_connections =
191     (osip_list_t *) osip_malloc (sizeof (osip_list_t));
192   osip_list_init ((*media)->c_connections);
193   (*media)->b_bandwidths = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
194   osip_list_init ((*media)->b_bandwidths);
195   (*media)->a_attributes = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
196   osip_list_init ((*media)->a_attributes);
197   (*media)->k_key = NULL;
198   return 0;
199 }
200
201 void
202 sdp_media_free (sdp_media_t * media)
203 {
204   if (media == NULL)
205     return;
206   osip_free (media->m_media);
207   osip_free (media->m_port);
208   osip_free (media->m_number_of_port);
209   osip_free (media->m_proto);
210   osip_list_ofchar_free (media->m_payloads);
211   osip_free (media->i_info);
212   osip_list_special_free (media->c_connections,
213                           (void *(*)(void *)) &sdp_connection_free);
214   osip_list_special_free (media->b_bandwidths,
215                           (void *(*)(void *)) &sdp_bandwidth_free);
216   osip_list_special_free (media->a_attributes,
217                           (void *(*)(void *)) &sdp_attribute_free);
218   sdp_key_free (media->k_key);
219   osip_free (media);
220 }
221
222 /* to be changed to sdp_message_init(sdp_message_t **dest) */
223 int
224 sdp_message_init (sdp_message_t ** sdp)
225 {
226   (*sdp) = (sdp_message_t *) osip_malloc (sizeof (sdp_message_t));
227   if (*sdp == NULL)
228     return -1;
229
230   (*sdp)->v_version = NULL;
231   (*sdp)->o_username = NULL;
232   (*sdp)->o_sess_id = NULL;
233   (*sdp)->o_sess_version = NULL;
234   (*sdp)->o_nettype = NULL;
235   (*sdp)->o_addrtype = NULL;
236   (*sdp)->o_addr = NULL;
237   (*sdp)->s_name = NULL;
238   (*sdp)->i_info = NULL;
239   (*sdp)->u_uri = NULL;
240
241   (*sdp)->e_emails = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
242   if ((*sdp)->e_emails == NULL)
243     return -1;
244   osip_list_init ((*sdp)->e_emails);
245
246   (*sdp)->p_phones = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
247   if ((*sdp)->p_phones == NULL)
248     return -1;
249   osip_list_init ((*sdp)->p_phones);
250
251   (*sdp)->c_connection = NULL;
252
253   (*sdp)->b_bandwidths = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
254   if ((*sdp)->b_bandwidths == NULL)
255     return -1;
256   osip_list_init ((*sdp)->b_bandwidths);
257
258   (*sdp)->t_descrs = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
259   if ((*sdp)->t_descrs == NULL)
260     return -1;
261   osip_list_init ((*sdp)->t_descrs);
262
263   (*sdp)->z_adjustments = NULL;
264   (*sdp)->k_key = NULL;
265
266   (*sdp)->a_attributes = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
267   if ((*sdp)->a_attributes == NULL)
268     return -1;
269   osip_list_init ((*sdp)->a_attributes);
270
271   (*sdp)->m_medias = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
272   if ((*sdp)->m_medias == NULL)
273     return -1;
274   osip_list_init ((*sdp)->m_medias);
275   return 0;
276 }
277
278 static int
279 sdp_message_parse_v (sdp_message_t * sdp, char *buf, char **next)
280 {
281   char *equal;
282   char *crlf;
283
284   *next = buf;
285
286   equal = buf;
287   while ((*equal != '=') && (*equal != '\0'))
288     equal++;
289   if (*equal == '\0')
290     return ERR_ERROR;
291
292   if (equal == buf)
293     return ERR_DISCARD;
294   
295   /* check if header is "v" */
296   if (equal[-1] != 'v')
297     return ERR_DISCARD;
298
299   crlf = equal + 1;
300
301   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
302     crlf++;
303   if (*crlf == '\0')
304     return ERR_ERROR;
305   if (crlf == equal + 1)
306     return ERR_ERROR;           /*v=\r ?? bad header */
307   sdp->v_version = osip_malloc (crlf - (equal + 1) + 1);
308   osip_strncpy (sdp->v_version, equal + 1, crlf - (equal + 1));
309
310   if (crlf[1] == '\n')
311     *next = crlf + 2;
312   else
313     *next = crlf + 1;
314   return WF;
315 }
316
317 static int
318 sdp_message_parse_o (sdp_message_t * sdp, char *buf, char **next)
319 {
320   char *equal;
321   char *crlf;
322   char *tmp;
323   char *tmp_next;
324   int i;
325
326   *next = buf;
327
328   equal = buf;
329   while ((*equal != '=') && (*equal != '\0'))
330     equal++;
331   if (*equal == '\0')
332     return ERR_ERROR;
333
334   /* check if header is "o" */
335   if (equal[-1] != 'o')
336     return ERR_DISCARD;
337
338   crlf = equal + 1;
339
340   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
341     crlf++;
342   if (*crlf == '\0')
343     return ERR_ERROR;
344   if (crlf == equal + 1)
345     return ERR_ERROR;           /* o=\r ?? bad header */
346
347   tmp = equal + 1;
348   /* o=username sess-id sess-version nettype addrtype addr */
349
350   /* useranme can contain any char (ascii) except "space" and CRLF */
351   i = __osip_set_next_token (&(sdp->o_username), tmp, ' ', &tmp_next);
352   if (i != 0)
353     return -1;
354   tmp = tmp_next;
355
356   /* sess_id contains only numeric characters */
357   i = __osip_set_next_token (&(sdp->o_sess_id), tmp, ' ', &tmp_next);
358   if (i != 0)
359     return -1;
360   tmp = tmp_next;
361
362   /* sess_id contains only numeric characters */
363   i = __osip_set_next_token (&(sdp->o_sess_version), tmp, ' ', &tmp_next);
364   if (i != 0)
365     return -1;
366   tmp = tmp_next;
367
368   /* nettype is "IN" but will surely be extented!!! assume it's some alpha-char */
369   i = __osip_set_next_token (&(sdp->o_nettype), tmp, ' ', &tmp_next);
370   if (i != 0)
371     return -1;
372   tmp = tmp_next;
373
374   /* addrtype  is "IP4" or "IP6" but will surely be extented!!! */
375   i = __osip_set_next_token (&(sdp->o_addrtype), tmp, ' ', &tmp_next);
376   if (i != 0)
377     return -1;
378   tmp = tmp_next;
379
380   /* addr  is "IP4" or "IP6" but will surely be extented!!! */
381   i = __osip_set_next_token (&(sdp->o_addr), tmp, '\r', &tmp_next);
382   if (i != 0)
383     {                           /* could it be "\n" only??? rfc says to accept CR or LF instead of CRLF */
384       i = __osip_set_next_token (&(sdp->o_addr), tmp, '\n', &tmp_next);
385       if (i != 0)
386         return -1;
387     }
388
389   if (crlf[1] == '\n')
390     *next = crlf + 2;
391   else
392     *next = crlf + 1;
393   return WF;
394 }
395
396 static int
397 sdp_message_parse_s (sdp_message_t * sdp, char *buf, char **next)
398 {
399   char *equal;
400   char *crlf;
401
402   *next = buf;
403
404   equal = buf;
405   while ((*equal != '=') && (*equal != '\0'))
406     equal++;
407   if (*equal == '\0')
408     return ERR_ERROR;
409
410   /* check if header is "s" */
411   if (equal[-1] != 's')
412     return ERR_DISCARD;
413
414   crlf = equal + 1;
415
416   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
417     crlf++;
418   if (*crlf == '\0')
419     return ERR_ERROR;
420   if (crlf == equal + 1)
421     return ERR_ERROR;           /* o=\r ?? bad header */
422
423   /* s=text */
424
425   /* text is interpreted as ISO-10646 UTF8! */
426   /* using ISO 8859-1 requires "a=charset:ISO-8859-1 */
427   sdp->s_name = osip_malloc (crlf - (equal + 1) + 1);
428   osip_strncpy (sdp->s_name, equal + 1, crlf - (equal + 1));
429
430   if (crlf[1] == '\n')
431     *next = crlf + 2;
432   else
433     *next = crlf + 1;
434   return WF;
435 }
436
437 static int
438 sdp_message_parse_i (sdp_message_t * sdp, char *buf, char **next)
439 {
440   char *equal;
441   char *crlf;
442   int i;
443   char *i_info;
444
445   *next = buf;
446
447   equal = buf;
448   while ((*equal != '=') && (*equal != '\0'))
449     equal++;
450   if (*equal == '\0')
451     return ERR_ERROR;
452
453   /* check if header is "i" */
454   if (equal[-1] != 'i')
455     return ERR_DISCARD;
456
457   crlf = equal + 1;
458
459   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
460     crlf++;
461   if (*crlf == '\0')
462     return ERR_ERROR;
463   if (crlf == equal + 1)
464     return ERR_ERROR;           /* o=\r ?? bad header */
465
466   /* s=text */
467
468   /* text is interpreted as ISO-10646 UTF8! */
469   /* using ISO 8859-1 requires "a=charset:ISO-8859-1 */
470   i_info = osip_malloc (crlf - (equal + 1) + 1);
471   osip_strncpy (i_info, equal + 1, crlf - (equal + 1));
472
473   /* add the bandwidth at the correct place:
474      if there is no media line yet, then the "b=" is the
475      global one.
476    */
477   i = osip_list_size (sdp->m_medias);
478   if (i == 0)
479     sdp->i_info = i_info;
480   else
481     {
482       sdp_media_t *last_sdp_media =
483         (sdp_media_t *) osip_list_get (sdp->m_medias, i - 1);
484       last_sdp_media->i_info = i_info;
485     }
486
487   if (crlf[1] == '\n')
488     *next = crlf + 2;
489   else
490     *next = crlf + 1;
491   return WF;
492 }
493
494 static int
495 sdp_message_parse_u (sdp_message_t * sdp, char *buf, char **next)
496 {
497   char *equal;
498   char *crlf;
499
500   *next = buf;
501
502   equal = buf;
503   while ((*equal != '=') && (*equal != '\0'))
504     equal++;
505   if (*equal == '\0')
506     return ERR_ERROR;
507
508   /* check if header is "u" */
509   if (equal[-1] != 'u')
510     return ERR_DISCARD;
511
512   crlf = equal + 1;
513
514   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
515     crlf++;
516   if (*crlf == '\0')
517     return ERR_ERROR;
518   if (crlf == equal + 1)
519     return ERR_ERROR;           /* u=\r ?? bad header */
520
521   /* u=uri */
522   /* we assume this is a URI */
523   sdp->u_uri = osip_malloc (crlf - (equal + 1) + 1);
524   osip_strncpy (sdp->u_uri, equal + 1, crlf - (equal + 1));
525
526   if (crlf[1] == '\n')
527     *next = crlf + 2;
528   else
529     *next = crlf + 1;
530   return WF;
531 }
532
533 static int
534 sdp_message_parse_e (sdp_message_t * sdp, char *buf, char **next)
535 {
536   char *equal;
537   char *crlf;
538   char *e_email;
539
540   *next = buf;
541
542   equal = buf;
543   while ((*equal != '=') && (*equal != '\0'))
544     equal++;
545   if (*equal == '\0')
546     return ERR_ERROR;
547
548   /* check if header is "e" */
549   if (equal[-1] != 'e')
550     return ERR_DISCARD;
551
552   crlf = equal + 1;
553
554   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
555     crlf++;
556   if (*crlf == '\0')
557     return ERR_ERROR;
558   if (crlf == equal + 1)
559     return ERR_ERROR;           /* e=\r ?? bad header */
560
561   /* e=email */
562   /* we assume this is an EMAIL-ADDRESS */
563   e_email = osip_malloc (crlf - (equal + 1) + 1);
564   osip_strncpy (e_email, equal + 1, crlf - (equal + 1));
565
566   osip_list_add (sdp->e_emails, e_email, -1);
567
568   if (crlf[1] == '\n')
569     *next = crlf + 2;
570   else
571     *next = crlf + 1;
572   return WF;
573 }
574
575 static int
576 sdp_message_parse_p (sdp_message_t * sdp, char *buf, char **next)
577 {
578   char *equal;
579   char *crlf;
580   char *p_phone;
581
582   *next = buf;
583
584   equal = buf;
585   while ((*equal != '=') && (*equal != '\0'))
586     equal++;
587   if (*equal == '\0')
588     return ERR_ERROR;
589
590   /* check if header is "p" */
591   if (equal[-1] != 'p')
592     return ERR_DISCARD;
593
594   crlf = equal + 1;
595
596   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
597     crlf++;
598   if (*crlf == '\0')
599     return ERR_ERROR;
600   if (crlf == equal + 1)
601     return ERR_ERROR;           /* p=\r ?? bad header */
602
603   /* e=email */
604   /* we assume this is an EMAIL-ADDRESS */
605   p_phone = osip_malloc (crlf - (equal + 1) + 1);
606   osip_strncpy (p_phone, equal + 1, crlf - (equal + 1));
607
608   osip_list_add (sdp->p_phones, p_phone, -1);
609
610   if (crlf[1] == '\n')
611     *next = crlf + 2;
612   else
613     *next = crlf + 1;
614   return WF;
615 }
616
617 static int
618 sdp_message_parse_c (sdp_message_t * sdp, char *buf, char **next)
619 {
620   char *equal;
621   char *crlf;
622   char *tmp;
623   char *tmp_next;
624   sdp_connection_t *c_header;
625   int i;
626
627   *next = buf;
628
629   equal = buf;
630   while ((*equal != '=') && (*equal != '\0'))
631     equal++;
632   if (*equal == '\0')
633     return ERR_ERROR;
634
635   /* check if header is "c" */
636   if (equal[-1] != 'c')
637     return ERR_DISCARD;
638
639   crlf = equal + 1;
640
641   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
642     crlf++;
643   if (*crlf == '\0')
644     return ERR_ERROR;
645   if (crlf == equal + 1)
646     return ERR_ERROR;           /* c=\r ?? bad header */
647
648   tmp = equal + 1;
649   i = sdp_connection_init (&c_header);
650   if (i != 0)
651     return ERR_ERROR;
652   /* c=nettype addrtype (multicastaddr | addr) */
653
654   /* nettype is "IN" and will be extended */
655   i = __osip_set_next_token (&(c_header->c_nettype), tmp, ' ', &tmp_next);
656   if (i != 0)
657     return -1;
658   tmp = tmp_next;
659
660   /* nettype is "IP4" or "IP6" and will be extended */
661   i = __osip_set_next_token (&(c_header->c_addrtype), tmp, ' ', &tmp_next);
662   if (i != 0)
663     return -1;
664   tmp = tmp_next;
665
666   /* there we have a multicast or unicast address */
667   /* multicast can be ip/ttl [/integer] */
668   /* unicast is FQDN or ip (no ttl, no integer) */
669
670   /* is MULTICAST? */
671   {
672     char *slash = strchr (tmp, '/');
673
674     if (slash != NULL && slash < crlf)  /* it's a multicast address! */
675       {
676         i = __osip_set_next_token (&(c_header->c_addr), tmp, '/', &tmp_next);
677         if (i != 0)
678           return -1;
679         tmp = tmp_next;
680         slash = strchr (slash + 1, '/');
681         if (slash != NULL && slash < crlf)      /* optionnal integer is there! */
682           {
683             i =
684               __osip_set_next_token (&(c_header->c_addr_multicast_ttl), tmp,
685                                      '/', &tmp_next);
686             if (i != 0)
687               return -1;
688             tmp = tmp_next;
689             i =
690               __osip_set_next_token (&(c_header->c_addr_multicast_int), tmp,
691                                      '\r', &tmp_next);
692             if (i != 0)
693               {
694                 i =
695                   __osip_set_next_token (&(c_header->c_addr_multicast_int),
696                                          tmp, '\n', &tmp_next);
697                 if (i != 0)
698                   {
699                     sdp_connection_free (c_header);
700                     return -1;
701                   }
702               }
703           }
704         else
705           {
706             i =
707               __osip_set_next_token (&(c_header->c_addr_multicast_ttl), tmp,
708                                      '\r', &tmp_next);
709             if (i != 0)
710               {
711                 i =
712                   __osip_set_next_token (&(c_header->c_addr_multicast_ttl),
713                                          tmp, '\n', &tmp_next);
714                 if (i != 0)
715                   {
716                     sdp_connection_free (c_header);
717                     return -1;
718                   }
719               }
720           }
721       }
722     else
723       {
724         /* in this case, we have a unicast address */
725         i = __osip_set_next_token (&(c_header->c_addr), tmp, '\r', &tmp_next);
726         if (i != 0)
727           {
728             i =
729               __osip_set_next_token (&(c_header->c_addr), tmp, '\n',
730                                      &tmp_next);
731             if (i != 0)
732               {
733                 sdp_connection_free (c_header);
734                 return -1;
735               }
736           }
737       }
738   }
739
740   /* add the connection at the correct place:
741      if there is no media line yet, then the "c=" is the
742      global one.
743    */
744   i = osip_list_size (sdp->m_medias);
745   if (i == 0)
746     sdp->c_connection = c_header;
747   else
748     {
749       sdp_media_t *last_sdp_media =
750         (sdp_media_t *) osip_list_get (sdp->m_medias, i - 1);
751       osip_list_add (last_sdp_media->c_connections, c_header, -1);
752     }
753   if (crlf[1] == '\n')
754     *next = crlf + 2;
755   else
756     *next = crlf + 1;
757   return WF;
758 }
759
760 static int
761 sdp_message_parse_b (sdp_message_t * sdp, char *buf, char **next)
762 {
763   char *equal;
764   char *crlf;
765   char *tmp;
766   char *tmp_next;
767   int i;
768   sdp_bandwidth_t *b_header;
769
770   *next = buf;
771
772   equal = buf;
773   while ((*equal != '=') && (*equal != '\0'))
774     equal++;
775   if (*equal == '\0')
776     return ERR_ERROR;
777
778   /* check if header is "b" */
779   if (equal[-1] != 'b')
780     return ERR_DISCARD;
781
782   crlf = equal + 1;
783
784   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
785     crlf++;
786   if (*crlf == '\0')
787     return ERR_ERROR;
788   if (crlf == equal + 1)
789     return ERR_ERROR;           /* b=\r ?? bad header */
790
791   tmp = equal + 1;
792   /* b = bwtype: bandwidth */
793   i = sdp_bandwidth_init (&b_header);
794   if (i != 0)
795     return ERR_ERROR;
796
797   /* bwtype is alpha-numeric */
798   i = __osip_set_next_token (&(b_header->b_bwtype), tmp, ':', &tmp_next);
799   if (i != 0)
800     return -1;
801   tmp = tmp_next;
802
803   i = __osip_set_next_token (&(b_header->b_bandwidth), tmp, '\r', &tmp_next);
804   if (i != 0)
805     {
806       i =
807         __osip_set_next_token (&(b_header->b_bandwidth), tmp, '\n',
808                                &tmp_next);
809       if (i != 0)
810         {
811           sdp_bandwidth_free (b_header);
812           return -1;
813         }
814     }
815
816   /* add the bandwidth at the correct place:
817      if there is no media line yet, then the "b=" is the
818      global one.
819    */
820   i = osip_list_size (sdp->m_medias);
821   if (i == 0)
822     osip_list_add (sdp->b_bandwidths, b_header, -1);
823   else
824     {
825       sdp_media_t *last_sdp_media =
826         (sdp_media_t *) osip_list_get (sdp->m_medias, i - 1);
827       osip_list_add (last_sdp_media->b_bandwidths, b_header, -1);
828     }
829
830   if (crlf[1] == '\n')
831     *next = crlf + 2;
832   else
833     *next = crlf + 1;
834   return WF;
835 }
836
837 static int
838 sdp_message_parse_t (sdp_message_t * sdp, char *buf, char **next)
839 {
840   char *equal;
841   char *crlf;
842   char *tmp;
843   char *tmp_next;
844   int i;
845   sdp_time_descr_t *t_header;
846
847   *next = buf;
848
849   equal = buf;
850   while ((*equal != '=') && (*equal != '\0'))
851     equal++;
852   if (*equal == '\0')
853     return ERR_ERROR;
854
855   /* check if header is "t" */
856   if (equal[-1] != 't')
857     return ERR_DISCARD;
858
859   crlf = equal + 1;
860
861   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
862     crlf++;
863   if (*crlf == '\0')
864     return ERR_ERROR;
865   if (crlf == equal + 1)
866     return ERR_ERROR;           /* t=\r ?? bad header */
867
868   tmp = equal + 1;
869   /* t = start_time stop_time */
870   i = sdp_time_descr_init (&t_header);
871   if (i != 0)
872     return ERR_ERROR;
873
874   i = __osip_set_next_token (&(t_header->t_start_time), tmp, ' ', &tmp_next);
875   if (i != 0)
876     {
877       sdp_time_descr_free (t_header);
878       return -1;
879     }
880   tmp = tmp_next;
881
882   i = __osip_set_next_token (&(t_header->t_stop_time), tmp, '\r', &tmp_next);
883   if (i != 0)
884     {
885       i =
886         __osip_set_next_token (&(t_header->t_stop_time), tmp, '\n',
887                                &tmp_next);
888       if (i != 0)
889         {
890           sdp_time_descr_free (t_header);
891           return -1;
892         }
893     }
894
895   /* add the new time_description header */
896   osip_list_add (sdp->t_descrs, t_header, -1);
897
898   if (crlf[1] == '\n')
899     *next = crlf + 2;
900   else
901     *next = crlf + 1;
902   return WF;
903 }
904
905 static int
906 sdp_message_parse_r (sdp_message_t * sdp, char *buf, char **next)
907 {
908   char *equal;
909   char *crlf;
910   int index;
911   char *r_header;
912   sdp_time_descr_t *t_descr;
913
914   *next = buf;
915
916   equal = buf;
917   while ((*equal != '=') && (*equal != '\0'))
918     equal++;
919   if (*equal == '\0')
920     return ERR_ERROR;
921
922   /* check if header is "r" */
923   if (equal[-1] != 'r')
924     return ERR_DISCARD;
925
926   index = osip_list_size (sdp->t_descrs);
927   if (index == 0)
928     return ERR_ERROR;           /* r field can't come alone! */
929
930   crlf = equal + 1;
931
932   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
933     crlf++;
934   if (*crlf == '\0')
935     return ERR_ERROR;
936   if (crlf == equal + 1)
937     return ERR_ERROR;           /* r=\r ?? bad header */
938
939   /* r=far too complexe and somewhat useless... I don't parse it! */
940   r_header = osip_malloc (crlf - (equal + 1) + 1);
941   osip_strncpy (r_header, equal + 1, crlf - (equal + 1));
942
943   /* r field carry information for the last "t" field */
944   t_descr = (sdp_time_descr_t *) osip_list_get (sdp->t_descrs, index - 1);
945   osip_list_add (t_descr->r_repeats, r_header, -1);
946
947   if (crlf[1] == '\n')
948     *next = crlf + 2;
949   else
950     *next = crlf + 1;
951   return WF;
952 }
953
954 static int
955 sdp_message_parse_z (sdp_message_t * sdp, char *buf, char **next)
956 {
957   char *equal;
958   char *crlf;
959   char *z_header;
960
961   *next = buf;
962
963   equal = buf;
964   while ((*equal != '=') && (*equal != '\0'))
965     equal++;
966   if (*equal == '\0')
967     return ERR_ERROR;
968
969   /* check if header is "z" */
970   if (equal[-1] != 'z')
971     return ERR_DISCARD;
972
973   crlf = equal + 1;
974
975   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
976     crlf++;
977   if (*crlf == '\0')
978     return ERR_ERROR;
979   if (crlf == equal + 1)
980     return ERR_ERROR;           /* z=\r ?? bad header */
981
982   /* z=somewhat useless... I don't parse it! */
983   z_header = osip_malloc (crlf - (equal + 1) + 1);
984   osip_strncpy (z_header, equal + 1, crlf - (equal + 1));
985
986   sdp->z_adjustments = z_header;
987
988   if (crlf[1] == '\n')
989     *next = crlf + 2;
990   else
991     *next = crlf + 1;
992   return WF;
993 }
994
995 static int
996 sdp_message_parse_k (sdp_message_t * sdp, char *buf, char **next)
997 {
998   char *equal;
999   char *crlf;
1000   int i;
1001   char *colon;
1002   sdp_key_t *k_header;
1003   char *tmp;
1004   char *tmp_next;
1005
1006   *next = buf;
1007
1008   equal = buf;
1009   while ((*equal != '=') && (*equal != '\0'))
1010     equal++;
1011   if (*equal == '\0')
1012     return ERR_ERROR;
1013
1014   /* check if header is "k" */
1015   if (equal[-1] != 'k')
1016     return ERR_DISCARD;
1017
1018   crlf = equal + 1;
1019
1020   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
1021     crlf++;
1022   if (*crlf == '\0')
1023     return ERR_ERROR;
1024   if (crlf == equal + 1)
1025     return ERR_ERROR;           /* k=\r ?? bad header */
1026
1027   tmp = equal + 1;
1028
1029   i = sdp_key_init (&k_header);
1030   if (i != 0)
1031     return ERR_ERROR;
1032   /* k=key-type[:key-data] */
1033
1034   /* is there any key-data? */
1035   colon = strchr (equal + 1, ':');
1036   if ((colon != NULL) && (colon < crlf))
1037     {
1038       /* att-field is alpha-numeric */
1039       i = __osip_set_next_token (&(k_header->k_keytype), tmp, ':', &tmp_next);
1040       if (i != 0)
1041         {
1042           sdp_key_free (k_header);
1043           return -1;
1044         }
1045       tmp = tmp_next;
1046
1047       i =
1048         __osip_set_next_token (&(k_header->k_keydata), tmp, '\r', &tmp_next);
1049       if (i != 0)
1050         {
1051           i =
1052             __osip_set_next_token (&(k_header->k_keydata), tmp, '\n',
1053                                    &tmp_next);
1054           if (i != 0)
1055             {
1056               sdp_key_free (k_header);
1057               return -1;
1058             }
1059         }
1060     }
1061   else
1062     {
1063       i =
1064         __osip_set_next_token (&(k_header->k_keytype), tmp, '\r', &tmp_next);
1065       if (i != 0)
1066         {
1067           i =
1068             __osip_set_next_token (&(k_header->k_keytype), tmp, '\n',
1069                                    &tmp_next);
1070           if (i != 0)
1071             {
1072               sdp_key_free (k_header);
1073               return -1;
1074             }
1075         }
1076     }
1077
1078   /* add the key at the correct place:
1079      if there is no media line yet, then the "k=" is the
1080      global one.
1081    */
1082   i = osip_list_size (sdp->m_medias);
1083   if (i == 0)
1084     sdp->k_key = k_header;
1085   else
1086     {
1087       sdp_media_t *last_sdp_media =
1088         (sdp_media_t *) osip_list_get (sdp->m_medias, i - 1);
1089       last_sdp_media->k_key = k_header;
1090     }
1091
1092   if (crlf[1] == '\n')
1093     *next = crlf + 2;
1094   else
1095     *next = crlf + 1;
1096   return WF;
1097 }
1098
1099 static int
1100 sdp_message_parse_a (sdp_message_t * sdp, char *buf, char **next)
1101 {
1102   char *equal;
1103   char *crlf;
1104   char *tmp;
1105   char *tmp_next;
1106   int i;
1107   sdp_attribute_t *a_attribute;
1108   char *colon;
1109
1110   *next = buf;
1111
1112   equal = buf;
1113   while ((*equal != '=') && (*equal != '\0'))
1114     equal++;
1115   if (*equal == '\0')
1116     return ERR_ERROR;
1117
1118   /* check if header is "a" */
1119   if (equal[-1] != 'a')
1120     return ERR_DISCARD;
1121
1122   crlf = equal + 1;
1123
1124   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
1125     crlf++;
1126   if (*crlf == '\0')
1127     return ERR_ERROR;
1128   if (crlf == equal + 1)
1129     return ERR_ERROR;           /* a=\r ?? bad header */
1130
1131   tmp = equal + 1;
1132
1133   i = sdp_attribute_init (&a_attribute);
1134   if (i != 0)
1135     return ERR_ERROR;
1136
1137   /* a=att-field[:att-value] */
1138
1139   /* is there any att-value? */
1140   colon = strchr (equal + 1, ':');
1141   if ((colon != NULL) && (colon < crlf))
1142     {
1143       /* att-field is alpha-numeric */
1144       i =
1145         __osip_set_next_token (&(a_attribute->a_att_field), tmp, ':',
1146                                &tmp_next);
1147       if (i != 0)
1148         {
1149           sdp_attribute_free (a_attribute);
1150           return -1;
1151         }
1152       tmp = tmp_next;
1153
1154       i =
1155         __osip_set_next_token (&(a_attribute->a_att_value), tmp, '\r',
1156                                &tmp_next);
1157       if (i != 0)
1158         {
1159           i =
1160             __osip_set_next_token (&(a_attribute->a_att_value), tmp, '\n',
1161                                    &tmp_next);
1162           if (i != 0)
1163             {
1164               sdp_attribute_free (a_attribute);
1165               return -1;
1166             }
1167         }
1168     }
1169   else
1170     {
1171       i =
1172         __osip_set_next_token (&(a_attribute->a_att_field), tmp, '\r',
1173                                &tmp_next);
1174       if (i != 0)
1175         {
1176           i =
1177             __osip_set_next_token (&(a_attribute->a_att_field), tmp, '\n',
1178                                    &tmp_next);
1179           if (i != 0)
1180             {
1181               sdp_attribute_free (a_attribute);
1182               return -1;
1183             }
1184         }
1185     }
1186
1187   /* add the attribute at the correct place:
1188      if there is no media line yet, then the "a=" is the
1189      global one.
1190    */
1191   i = osip_list_size (sdp->m_medias);
1192   if (i == 0)
1193     osip_list_add (sdp->a_attributes, a_attribute, -1);
1194   else
1195     {
1196       sdp_media_t *last_sdp_media =
1197         (sdp_media_t *) osip_list_get (sdp->m_medias, i - 1);
1198       osip_list_add (last_sdp_media->a_attributes, a_attribute, -1);
1199     }
1200
1201   if (crlf[1] == '\n')
1202     *next = crlf + 2;
1203   else
1204     *next = crlf + 1;
1205   return WF;
1206 }
1207
1208 static int
1209 sdp_message_parse_m (sdp_message_t * sdp, char *buf, char **next)
1210 {
1211   char *equal;
1212   char *crlf;
1213   char *tmp;
1214   char *tmp_next;
1215   int i;
1216   sdp_media_t *m_header;
1217   char *slash;
1218   char *space;
1219
1220   *next = buf;
1221
1222   equal = buf;
1223   while ((*equal != '=') && (*equal != '\0'))
1224     equal++;
1225   if (*equal == '\0')
1226     return ERR_ERROR;
1227
1228   /* check if header is "m" */
1229   if (equal[-1] != 'm')
1230     return ERR_DISCARD;
1231
1232   crlf = equal + 1;
1233
1234   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
1235     crlf++;
1236   if (*crlf == '\0')
1237     return ERR_ERROR;
1238   if (crlf == equal + 1)
1239     return ERR_ERROR;           /* a=\r ?? bad header */
1240
1241   tmp = equal + 1;
1242
1243   i = sdp_media_init (&m_header);
1244   if (i != 0)
1245     return ERR_ERROR;
1246
1247   /* m=media port ["/"integer] proto *(payload_number) */
1248
1249   /* media is "audio" "video" "application" "data" or other... */
1250   i = __osip_set_next_token (&(m_header->m_media), tmp, ' ', &tmp_next);
1251   if (i != 0)
1252     {
1253       sdp_media_free (m_header);
1254       return -1;
1255     }
1256   tmp = tmp_next;
1257
1258   slash = strchr (tmp, '/');
1259   space = strchr (tmp, ' ');
1260   if (space == NULL)            /* not possible! */
1261     {
1262       sdp_media_free (m_header);
1263       return ERR_ERROR;
1264     }
1265   if ((slash != NULL) && (slash < space))
1266     {                           /* a number of port is specified! */
1267       i = __osip_set_next_token (&(m_header->m_port), tmp, '/', &tmp_next);
1268       if (i != 0)
1269         {
1270           sdp_media_free (m_header);
1271           return -1;
1272         }
1273       tmp = tmp_next;
1274
1275       i =
1276         __osip_set_next_token (&(m_header->m_number_of_port), tmp, ' ',
1277                                &tmp_next);
1278       if (i != 0)
1279         {
1280           sdp_media_free (m_header);
1281           return -1;
1282         }
1283       tmp = tmp_next;
1284     }
1285   else
1286     {
1287       i = __osip_set_next_token (&(m_header->m_port), tmp, ' ', &tmp_next);
1288       if (i != 0)
1289         {
1290           sdp_media_free (m_header);
1291           return -1;
1292         }
1293       tmp = tmp_next;
1294     }
1295
1296   i = __osip_set_next_token (&(m_header->m_proto), tmp, ' ', &tmp_next);
1297   if (i != 0)
1298     {
1299       sdp_media_free (m_header);
1300       return -1;
1301     }
1302   tmp = tmp_next;
1303
1304   {
1305     char *str;
1306     int more_space_before_crlf;
1307
1308     space = strchr (tmp + 1, ' ');
1309     if (space == NULL)
1310       more_space_before_crlf = 1;
1311     else if ((space != NULL) && (space > crlf))
1312       more_space_before_crlf = 1;
1313     else
1314       more_space_before_crlf = 0;
1315     while (more_space_before_crlf == 0)
1316       {
1317         i = __osip_set_next_token (&str, tmp, ' ', &tmp_next);
1318         if (i != 0)
1319           {
1320             sdp_media_free (m_header);
1321             return -1;
1322           }
1323         tmp = tmp_next;
1324         osip_list_add (m_header->m_payloads, str, -1);
1325
1326         space = strchr (tmp + 1, ' ');
1327         if (space == NULL)
1328           more_space_before_crlf = 1;
1329         else if ((space != NULL) && (space > crlf))
1330           more_space_before_crlf = 1;
1331         else
1332           more_space_before_crlf = 0;
1333       }
1334     if (tmp_next < crlf)
1335       {                         /* tmp_next is still less than clrf: no space */
1336         i = __osip_set_next_token (&str, tmp, '\r', &tmp_next);
1337         if (i != 0)
1338           {
1339             i = __osip_set_next_token (&str, tmp, '\n', &tmp_next);
1340             if (i != 0)
1341               {
1342                 sdp_media_free (m_header);
1343                 return -1;
1344               }
1345           }
1346         osip_list_add (m_header->m_payloads, str, -1);
1347       }
1348   }
1349
1350   osip_list_add (sdp->m_medias, m_header, -1);
1351
1352   if (crlf[1] == '\n')
1353     *next = crlf + 2;
1354   else
1355     *next = crlf + 1;
1356   return WF;
1357 }
1358
1359
1360 int
1361 sdp_message_parse (sdp_message_t * sdp, const char *buf)
1362 {
1363
1364   /* In SDP, headers must be in the right order */
1365   /* This is a simple example
1366      v=0
1367      o=user1 53655765 2353687637 IN IP4 128.3.4.5
1368      s=Mbone Audio
1369      i=Discussion of Mbone Engineering Issues
1370      e=mbone@somewhere.com
1371      c=IN IP4 224.2.0.1/127
1372      t=0 0
1373      m=audio 3456 RTP/AVP 0
1374      a=rtpmap:0 PCMU/8000
1375    */
1376
1377   char *next_buf;
1378   char *ptr;
1379   int i;
1380
1381   ptr = (char *) buf;
1382   /* mandatory */
1383   i = sdp_message_parse_v (sdp, ptr, &next_buf);
1384   if (i == -1)                  /* header is bad */
1385     return -1;
1386   else if (0 == i)              /* header is not "v" */
1387     return -1;
1388   ptr = next_buf;
1389
1390   /* adtech phone use the wrong ordering and place "s" before "o" */
1391   i = sdp_message_parse_s (sdp, ptr, &next_buf);
1392   if (i == -1)                  /* header is bad */
1393     return -1;
1394   /* else if (0==i) header is not "s" */
1395   /* else ADTECH PHONE DETECTED */
1396
1397   ptr = next_buf;
1398
1399
1400
1401   i = sdp_message_parse_o (sdp, ptr, &next_buf);
1402   if (i == -1)                  /* header is bad */
1403     return -1;
1404   else if (0 == i)              /* header is not "o" */
1405     return -1;
1406   ptr = next_buf;
1407
1408   i = sdp_message_parse_s (sdp, ptr, &next_buf);
1409   if (i == -1)                  /* header is bad */
1410     return -1;
1411   else if (0 == i)              /* header is not "s" */
1412     /* return -1; */
1413     {
1414       OSIP_TRACE (osip_trace
1415                   (__FILE__, __LINE__, OSIP_INFO4, NULL,
1416                    "The \"s\" parameter is mandatory, but this packet does not contain any! - anyway, we don't mind about it.\n"));
1417     }
1418   ptr = next_buf;
1419
1420   i = sdp_message_parse_i (sdp, ptr, &next_buf);
1421   if (i == -1)                  /* header is bad */
1422     return -1;
1423   ptr = next_buf;
1424
1425   i = sdp_message_parse_u (sdp, ptr, &next_buf);
1426   if (i == -1)                  /* header is bad */
1427     return -1;
1428   ptr = next_buf;
1429
1430   i = 1;
1431   while (i == 1)
1432     {
1433       i = sdp_message_parse_e (sdp, ptr, &next_buf);
1434       if (i == -1)              /* header is bad */
1435         return -1;
1436       ptr = next_buf;
1437     }
1438   i = 1;
1439   while (i == 1)
1440     {
1441       i = sdp_message_parse_p (sdp, ptr, &next_buf);
1442       if (i == -1)              /* header is bad */
1443         return -1;
1444       ptr = next_buf;
1445     }
1446
1447   /* rfc2327: there should be at least of email or phone number! */
1448   if (osip_list_size (sdp->e_emails) == 0
1449       && osip_list_size (sdp->p_phones) == 0)
1450     {
1451       OSIP_TRACE (osip_trace
1452                   (__FILE__, __LINE__, OSIP_INFO4, NULL,
1453                    "The rfc2327 says there should be at least an email or a phone header!- anyway, we don't mind about it.\n"));
1454     }
1455
1456   i = sdp_message_parse_c (sdp, ptr, &next_buf);
1457   if (i == -1)                  /* header is bad */
1458     return -1;
1459   ptr = next_buf;
1460
1461   i = 1;
1462   while (i == 1)
1463     {
1464       i = sdp_message_parse_b (sdp, ptr, &next_buf);
1465       if (i == -1)              /* header is bad */
1466         return -1;
1467       ptr = next_buf;
1468     }
1469
1470   /* 1 or more "t" header + 0 or more "r" header for each "t" header */
1471   i = sdp_message_parse_t (sdp, ptr, &next_buf);
1472   if (i == -1)                  /* header is bad */
1473     return -1;
1474   else if (i == ERR_DISCARD)
1475     return -1;                  /* t is mandatory */
1476   ptr = next_buf;
1477
1478   if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1479     return 0;
1480
1481   i = 1;
1482   while (i == 1)                /* is a "r" header */
1483     {
1484       i = sdp_message_parse_r (sdp, ptr, &next_buf);
1485       if (i == -1)              /* header is bad */
1486         return -1;
1487       ptr = next_buf;
1488       if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1489         return 0;
1490
1491     }
1492
1493
1494   {
1495     int more_t_header = 1;
1496
1497     i = sdp_message_parse_t (sdp, ptr, &next_buf);
1498     if (i == -1)                /* header is bad */
1499       return -1;
1500     ptr = next_buf;
1501
1502     if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1503       return 0;
1504
1505     while (more_t_header == 1)
1506       {
1507         i = 1;
1508         while (i == 1)          /* is a "r" header */
1509           {
1510             i = sdp_message_parse_r (sdp, ptr, &next_buf);
1511             if (i == -1)        /* header is bad */
1512               return -1;
1513             ptr = next_buf;
1514             if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1515               return 0;
1516           }
1517
1518         i = sdp_message_parse_t (sdp, ptr, &next_buf);
1519         if (i == -1)            /* header is bad */
1520           return -1;
1521         else if (i == ERR_DISCARD)
1522           more_t_header = 0;
1523         else
1524           more_t_header = 1;    /* no more "t" headers */
1525         ptr = next_buf;
1526         if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1527           return 0;
1528       }
1529   }
1530
1531   i = sdp_message_parse_z (sdp, ptr, &next_buf);
1532   if (i == -1)                  /* header is bad */
1533     return -1;
1534   ptr = next_buf;
1535   if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1536     return 0;
1537
1538   i = sdp_message_parse_k (sdp, ptr, &next_buf);
1539   if (i == -1)                  /* header is bad */
1540     return -1;
1541   ptr = next_buf;
1542   if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1543     return 0;
1544
1545   /* 0 or more "a" header */
1546   i = 1;
1547   while (i == 1)                /* no more "a" header */
1548     {
1549       i = sdp_message_parse_a (sdp, ptr, &next_buf);
1550       if (i == -1)              /* header is bad */
1551         return -1;
1552       ptr = next_buf;
1553       if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1554         return 0;
1555     }
1556   /* 0 or more media headers */
1557   {
1558     int more_m_header = 1;
1559
1560     while (more_m_header == 1)
1561       {
1562         more_m_header = sdp_message_parse_m (sdp, ptr, &next_buf);
1563         if (more_m_header == -1)        /* header is bad */
1564           return -1;
1565         ptr = next_buf;
1566         if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1567           return 0;
1568
1569         i = sdp_message_parse_i (sdp, ptr, &next_buf);
1570         if (i == -1)            /* header is bad */
1571           return -1;
1572         ptr = next_buf;
1573         if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1574           return 0;
1575
1576         i = 1;
1577         while (i == 1)
1578           {
1579             i = sdp_message_parse_c (sdp, ptr, &next_buf);
1580             if (i == -1)        /* header is bad */
1581               return -1;
1582             ptr = next_buf;
1583             if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1584               return 0;
1585           }
1586
1587         i = 1;
1588         while (i == 1)
1589           {
1590             i = sdp_message_parse_b (sdp, ptr, &next_buf);
1591             if (i == -1)        /* header is bad */
1592               return -1;
1593             ptr = next_buf;
1594             if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1595               return 0;
1596           }
1597         i = sdp_message_parse_k (sdp, ptr, &next_buf);
1598         if (i == -1)            /* header is bad */
1599           return -1;
1600         ptr = next_buf;
1601         if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1602           return 0;
1603         /* 0 or more a headers */
1604         i = 1;
1605         while (i == 1)
1606           {
1607             i = sdp_message_parse_a (sdp, ptr, &next_buf);
1608             if (i == -1)        /* header is bad */
1609               return -1;
1610             ptr = next_buf;
1611             if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
1612               return 0;
1613           }
1614       }
1615   }
1616
1617   return 0;
1618 }
1619
1620 static int
1621 sdp_append_connection (char *string, int size, char *tmp,
1622                        sdp_connection_t * conn, char **next_tmp)
1623 {
1624   if (conn->c_nettype == NULL)
1625     return -1;
1626   if (conn->c_addrtype == NULL)
1627     return -1;
1628   if (conn->c_addr == NULL)
1629     return -1;
1630
1631   tmp = __osip_sdp_append_string (string, size, tmp, "c=");
1632   tmp = __osip_sdp_append_string (string, size, tmp, conn->c_nettype);
1633   tmp = __osip_sdp_append_string (string, size, tmp, " ");
1634   tmp = __osip_sdp_append_string (string, size, tmp, conn->c_addrtype);
1635   tmp = __osip_sdp_append_string (string, size, tmp, " ");
1636   tmp = __osip_sdp_append_string (string, size, tmp, conn->c_addr);
1637   if (conn->c_addr_multicast_ttl != NULL)
1638     {
1639       tmp = __osip_sdp_append_string (string, size, tmp, "/");
1640       tmp =
1641         __osip_sdp_append_string (string, size, tmp,
1642                                   conn->c_addr_multicast_ttl);
1643     }
1644   if (conn->c_addr_multicast_int != NULL)
1645     {
1646       tmp = __osip_sdp_append_string (string, size, tmp, "/");
1647       tmp =
1648         __osip_sdp_append_string (string, size, tmp,
1649                                   conn->c_addr_multicast_int);
1650     }
1651   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1652   *next_tmp = tmp;
1653   return 0;
1654 }
1655
1656 static int
1657 sdp_append_bandwidth (char *string, int size, char *tmp,
1658                       sdp_bandwidth_t * bandwidth, char **next_tmp)
1659 {
1660   if (bandwidth->b_bwtype == NULL)
1661     return -1;
1662   if (bandwidth->b_bandwidth == NULL)
1663     return -1;
1664
1665   tmp = __osip_sdp_append_string (string, size, tmp, "b=");
1666   tmp = __osip_sdp_append_string (string, size, tmp, bandwidth->b_bwtype);
1667   tmp = __osip_sdp_append_string (string, size, tmp, ":");
1668   tmp = __osip_sdp_append_string (string, size, tmp, bandwidth->b_bandwidth);
1669   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1670
1671   *next_tmp = tmp;
1672   return 0;
1673 }
1674
1675 static int
1676 sdp_append_time_descr (char *string, int size, char *tmp,
1677                        sdp_time_descr_t * time_descr, char **next_tmp)
1678 {
1679   int pos;
1680
1681   if (time_descr->t_start_time == NULL)
1682     return -1;
1683   if (time_descr->t_stop_time == NULL)
1684     return -1;
1685
1686
1687   tmp = __osip_sdp_append_string (string, size, tmp, "t=");
1688   tmp =
1689     __osip_sdp_append_string (string, size, tmp, time_descr->t_start_time);
1690   tmp = __osip_sdp_append_string (string, size, tmp, " ");
1691   tmp = __osip_sdp_append_string (string, size, tmp, time_descr->t_stop_time);
1692
1693   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1694
1695   pos = 0;
1696   while (!osip_list_eol (time_descr->r_repeats, pos))
1697     {
1698       char *str = (char *) osip_list_get (time_descr->r_repeats, pos);
1699
1700       tmp = __osip_sdp_append_string (string, size, tmp, "r=");
1701       tmp = __osip_sdp_append_string (string, size, tmp, str);
1702       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1703       pos++;
1704     }
1705
1706   *next_tmp = tmp;
1707   return 0;
1708 }
1709
1710 static int
1711 sdp_append_key (char *string, int size, char *tmp, sdp_key_t * key,
1712                 char **next_tmp)
1713 {
1714   if (key->k_keytype == NULL)
1715     return -1;
1716
1717   tmp = __osip_sdp_append_string (string, size, tmp, "k=");
1718   tmp = __osip_sdp_append_string (string, size, tmp, key->k_keytype);
1719   if (key->k_keydata != NULL)
1720     {
1721       tmp = __osip_sdp_append_string (string, size, tmp, ":");
1722       tmp = __osip_sdp_append_string (string, size, tmp, key->k_keydata);
1723     }
1724   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1725   *next_tmp = tmp;
1726   return 0;
1727 }
1728
1729 static int
1730 sdp_append_attribute (char *string, int size, char *tmp,
1731                       sdp_attribute_t * attribute, char **next_tmp)
1732 {
1733   if (attribute->a_att_field == NULL)
1734     return -1;
1735
1736   tmp = __osip_sdp_append_string (string, size, tmp, "a=");
1737   tmp = __osip_sdp_append_string (string, size, tmp, attribute->a_att_field);
1738   if (attribute->a_att_value != NULL)
1739     {
1740       tmp = __osip_sdp_append_string (string, size, tmp, ":");
1741       tmp =
1742         __osip_sdp_append_string (string, size, tmp, attribute->a_att_value);
1743     }
1744   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1745
1746   *next_tmp = tmp;
1747   return 0;
1748 }
1749
1750 /* internal facility */
1751 static int
1752 sdp_append_media (char *string, int size, char *tmp, sdp_media_t * media,
1753                   char **next_tmp)
1754 {
1755   int pos;
1756
1757   if (media->m_media == NULL)
1758     return -1;
1759   if (media->m_port == NULL)
1760     return -1;
1761   if (media->m_proto == NULL)
1762     return -1;
1763
1764   tmp = __osip_sdp_append_string (string, size, tmp, "m=");
1765   tmp = __osip_sdp_append_string (string, size, tmp, media->m_media);
1766   tmp = __osip_sdp_append_string (string, size, tmp, " ");
1767   tmp = __osip_sdp_append_string (string, size, tmp, media->m_port);
1768   if (media->m_number_of_port != NULL)
1769     {
1770       tmp = __osip_sdp_append_string (string, size, tmp, "/");
1771       tmp =
1772         __osip_sdp_append_string (string, size, tmp, media->m_number_of_port);
1773     }
1774   tmp = __osip_sdp_append_string (string, size, tmp, " ");
1775   tmp = __osip_sdp_append_string (string, size, tmp, media->m_proto);
1776   pos = 0;
1777   while (!osip_list_eol (media->m_payloads, pos))
1778     {
1779       char *str = (char *) osip_list_get (media->m_payloads, pos);
1780
1781       tmp = __osip_sdp_append_string (string, size, tmp, " ");
1782       tmp = __osip_sdp_append_string (string, size, tmp, str);
1783       pos++;
1784     }
1785   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1786
1787   if (media->i_info != NULL)
1788     {
1789       tmp = __osip_sdp_append_string (string, size, tmp, "i=");
1790       tmp = __osip_sdp_append_string (string, size, tmp, media->i_info);
1791       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1792     }
1793
1794   pos = 0;
1795   while (!osip_list_eol (media->c_connections, pos))
1796     {
1797       sdp_connection_t *conn =
1798         (sdp_connection_t *) osip_list_get (media->c_connections, pos);
1799       char *next_tmp2;
1800       int i;
1801
1802       i = sdp_append_connection (string, size, tmp, conn, &next_tmp2);
1803       if (i != 0)
1804         return -1;
1805       tmp = next_tmp2;
1806       pos++;
1807     }
1808
1809   pos = 0;
1810   while (!osip_list_eol (media->b_bandwidths, pos))
1811     {
1812       sdp_bandwidth_t *band =
1813         (sdp_bandwidth_t *) osip_list_get (media->b_bandwidths, pos);
1814       char *next_tmp2;
1815       int i;
1816
1817       i = sdp_append_bandwidth (string, size, tmp, band, &next_tmp2);
1818       if (i != 0)
1819         return -1;
1820       tmp = next_tmp2;
1821       pos++;
1822     }
1823
1824   if (media->k_key != NULL)
1825     {
1826       char *next_tmp2;
1827       int i;
1828
1829       i = sdp_append_key (string, size, tmp, media->k_key, &next_tmp2);
1830       if (i != 0)
1831         return -1;
1832       tmp = next_tmp2;
1833     }
1834
1835   pos = 0;
1836   while (!osip_list_eol (media->a_attributes, pos))
1837     {
1838       sdp_attribute_t *attr =
1839         (sdp_attribute_t *) osip_list_get (media->a_attributes, pos);
1840       char *next_tmp2;
1841       int i;
1842
1843       i = sdp_append_attribute (string, size, tmp, attr, &next_tmp2);
1844       if (i != 0)
1845         return -1;
1846       tmp = next_tmp2;
1847       pos++;
1848     }
1849
1850   *next_tmp = tmp;
1851   return 0;
1852 }
1853
1854 int
1855 sdp_message_to_str (sdp_message_t * sdp, char **dest)
1856 {
1857   int size;
1858   int pos;
1859   char *tmp;
1860   char *string;
1861
1862   *dest = NULL;
1863   if (sdp->v_version == NULL)
1864     return -1;
1865   if (sdp->o_username == NULL ||
1866       sdp->o_sess_id == NULL ||
1867       sdp->o_sess_version == NULL ||
1868       sdp->o_nettype == NULL || sdp->o_addrtype == NULL
1869       || sdp->o_addr == NULL)
1870     return -1;
1871
1872   /* RFC says "s=" is mandatory... rfc2543 (SIP) recommends to
1873      accept SDP datas without s_name... as some buggy implementations
1874      often forget it...
1875    */
1876   /* if (sdp->s_name == NULL)
1877      return -1; */
1878
1879   size = 4000;
1880   tmp = (char *) osip_malloc (size);
1881   string = tmp;
1882
1883   tmp = __osip_sdp_append_string (string, size, tmp, "v=");
1884   tmp = __osip_sdp_append_string (string, size, tmp, sdp->v_version);
1885   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1886   tmp = __osip_sdp_append_string (string, size, tmp, "o=");
1887   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_username);
1888   tmp = __osip_sdp_append_string (string, size, tmp, " ");
1889   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_sess_id);
1890   tmp = __osip_sdp_append_string (string, size, tmp, " ");
1891   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_sess_version);
1892   tmp = __osip_sdp_append_string (string, size, tmp, " ");
1893   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_nettype);
1894   tmp = __osip_sdp_append_string (string, size, tmp, " ");
1895   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_addrtype);
1896   tmp = __osip_sdp_append_string (string, size, tmp, " ");
1897   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_addr);
1898   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1899   if (sdp->s_name != NULL)
1900     {
1901       tmp = __osip_sdp_append_string (string, size, tmp, "s=");
1902       tmp = __osip_sdp_append_string (string, size, tmp, sdp->s_name);
1903       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1904     }
1905   if (sdp->i_info != NULL)
1906     {
1907       tmp = __osip_sdp_append_string (string, size, tmp, "i=");
1908       tmp = __osip_sdp_append_string (string, size, tmp, sdp->i_info);
1909       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1910     }
1911   if (sdp->u_uri != NULL)
1912     {
1913       tmp = __osip_sdp_append_string (string, size, tmp, "u=");
1914       tmp = __osip_sdp_append_string (string, size, tmp, sdp->u_uri);
1915       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1916     }
1917   pos = 0;
1918   while (!osip_list_eol (sdp->e_emails, pos))
1919     {
1920       char *email = (char *) osip_list_get (sdp->e_emails, pos);
1921
1922       tmp = __osip_sdp_append_string (string, size, tmp, "e=");
1923       tmp = __osip_sdp_append_string (string, size, tmp, email);
1924       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1925       pos++;
1926     }
1927   pos = 0;
1928   while (!osip_list_eol (sdp->p_phones, pos))
1929     {
1930       char *phone = (char *) osip_list_get (sdp->p_phones, pos);
1931
1932       tmp = __osip_sdp_append_string (string, size, tmp, "p=");
1933       tmp = __osip_sdp_append_string (string, size, tmp, phone);
1934       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1935       pos++;
1936     }
1937   if (sdp->c_connection != NULL)
1938     {
1939       char *next_tmp;
1940       int i;
1941
1942       i =
1943         sdp_append_connection (string, size, tmp, sdp->c_connection,
1944                                &next_tmp);
1945       if (i != 0)
1946         return -1;
1947       tmp = next_tmp;
1948     }
1949   pos = 0;
1950   while (!osip_list_eol (sdp->b_bandwidths, pos))
1951     {
1952       sdp_bandwidth_t *header =
1953         (sdp_bandwidth_t *) osip_list_get (sdp->b_bandwidths, pos);
1954       char *next_tmp;
1955       int i;
1956
1957       i = sdp_append_bandwidth (string, size, tmp, header, &next_tmp);
1958       if (i != 0)
1959         return -1;
1960       tmp = next_tmp;
1961       pos++;
1962     }
1963
1964   pos = 0;
1965   while (!osip_list_eol (sdp->t_descrs, pos))
1966     {
1967       sdp_time_descr_t *header =
1968         (sdp_time_descr_t *) osip_list_get (sdp->t_descrs, pos);
1969       char *next_tmp;
1970       int i;
1971
1972       i = sdp_append_time_descr (string, size, tmp, header, &next_tmp);
1973       if (i != 0)
1974         return -1;
1975       tmp = next_tmp;
1976       pos++;
1977     }
1978
1979   if (sdp->z_adjustments != NULL)
1980     {
1981       tmp = __osip_sdp_append_string (string, size, tmp, "z=");
1982       tmp = __osip_sdp_append_string (string, size, tmp, sdp->z_adjustments);
1983       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
1984     }
1985
1986   if (sdp->k_key != NULL)
1987     {
1988       char *next_tmp;
1989       int i;
1990
1991       i = sdp_append_key (string, size, tmp, sdp->k_key, &next_tmp);
1992       if (i != 0)
1993         return -1;
1994       tmp = next_tmp;
1995     }
1996
1997   pos = 0;
1998   while (!osip_list_eol (sdp->a_attributes, pos))
1999     {
2000       sdp_attribute_t *header =
2001         (sdp_attribute_t *) osip_list_get (sdp->a_attributes, pos);
2002       char *next_tmp;
2003       int i;
2004
2005       i = sdp_append_attribute (string, size, tmp, header, &next_tmp);
2006       if (i != 0)
2007         return -1;
2008       tmp = next_tmp;
2009       pos++;
2010     }
2011
2012   pos = 0;
2013   while (!osip_list_eol (sdp->m_medias, pos))
2014     {
2015       sdp_media_t *header =
2016         (sdp_media_t *) osip_list_get (sdp->m_medias, pos);
2017       char *next_tmp;
2018       int i;
2019
2020       i = sdp_append_media (string, size, tmp, header, &next_tmp);
2021       if (i != 0)
2022         return -1;
2023       tmp = next_tmp;
2024       pos++;
2025     }
2026   *dest = string;
2027   return 0;
2028 }
2029
2030 void
2031 sdp_message_free (sdp_message_t * sdp)
2032 {
2033   if (sdp == NULL)
2034     return;
2035   osip_free (sdp->v_version);
2036   osip_free (sdp->o_username);
2037   osip_free (sdp->o_sess_id);
2038   osip_free (sdp->o_sess_version);
2039   osip_free (sdp->o_nettype);
2040   osip_free (sdp->o_addrtype);
2041   osip_free (sdp->o_addr);
2042   osip_free (sdp->s_name);
2043   osip_free (sdp->i_info);
2044   osip_free (sdp->u_uri);
2045
2046   osip_list_ofchar_free (sdp->e_emails);
2047
2048   osip_list_ofchar_free (sdp->p_phones);
2049
2050   sdp_connection_free (sdp->c_connection);
2051
2052   osip_list_special_free (sdp->b_bandwidths,
2053                           (void *(*)(void *)) &sdp_bandwidth_free);
2054
2055   osip_list_special_free (sdp->t_descrs,
2056                           (void *(*)(void *)) &sdp_time_descr_free);
2057
2058   osip_free (sdp->z_adjustments);
2059   sdp_key_free (sdp->k_key);
2060
2061   osip_list_special_free (sdp->a_attributes,
2062                           (void *(*)(void *)) &sdp_attribute_free);
2063
2064   osip_list_special_free (sdp->m_medias, (void *(*)(void *)) &sdp_media_free);
2065
2066   osip_free (sdp);
2067 }
2068
2069 int
2070 sdp_message_clone (sdp_message_t * sdp, sdp_message_t ** dest)
2071 {
2072   int i;
2073   char *body;
2074
2075   i = sdp_message_init (dest);
2076   if (i != 0)
2077     return -1;
2078
2079   i = sdp_message_to_str (sdp, &body);
2080   if (i != 0)
2081     goto error_sc1;
2082
2083   i = sdp_message_parse (*dest, body);
2084   osip_free (body);
2085   if (i != 0)
2086     goto error_sc1;
2087
2088   return 0;
2089
2090 error_sc1:
2091   sdp_message_free (*dest);
2092   return -1;
2093 }