sdp_message.c

Go to the documentation of this file.
00001 
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 
00026 #include "osip_const.h"
00027 #include "sdp_message.h"
00028 #include "osip_port.h"
00029 
00030 #define ERR_ERROR   -1          /* bad header */
00031 #define ERR_DISCARD  0          /* wrong header */
00032 #define WF           1          /* well formed header */
00033 
00034 static int sdp_message_parse_v (sdp_message_t * sdp, char *buf, char **next);
00035 static int sdp_message_parse_o (sdp_message_t * sdp, char *buf, char **next);
00036 static int sdp_message_parse_s (sdp_message_t * sdp, char *buf, char **next);
00037 static int sdp_message_parse_i (sdp_message_t * sdp, char *buf, char **next);
00038 static int sdp_message_parse_u (sdp_message_t * sdp, char *buf, char **next);
00039 static int sdp_message_parse_e (sdp_message_t * sdp, char *buf, char **next);
00040 static int sdp_message_parse_p (sdp_message_t * sdp, char *buf, char **next);
00041 static int sdp_message_parse_c (sdp_message_t * sdp, char *buf, char **next);
00042 static int sdp_message_parse_b (sdp_message_t * sdp, char *buf, char **next);
00043 static int sdp_message_parse_t (sdp_message_t * sdp, char *buf, char **next);
00044 static int sdp_message_parse_r (sdp_message_t * sdp, char *buf, char **next);
00045 static int sdp_message_parse_z (sdp_message_t * sdp, char *buf, char **next);
00046 static int sdp_message_parse_k (sdp_message_t * sdp, char *buf, char **next);
00047 static int sdp_message_parse_a (sdp_message_t * sdp, char *buf, char **next);
00048 static int sdp_message_parse_m (sdp_message_t * sdp, char *buf, char **next);
00049 
00050 static int sdp_append_media (char *string, int size, char *tmp,
00051                              sdp_media_t * media, char **next_tmp);
00052 static int sdp_append_attribute (char *string, int size, char *tmp,
00053                                  sdp_attribute_t * attribute, char **next_tmp);
00054 static int sdp_append_key (char *string, int size, char *tmp, sdp_key_t * key,
00055                            char **next_tmp);
00056 static int sdp_append_time_descr (char *string, int size, char *tmp,
00057                                   sdp_time_descr_t * time_descr, char **next_tmp);
00058 static int sdp_append_bandwidth (char *string, int size, char *tmp,
00059                                  sdp_bandwidth_t * bandwidth, char **next_tmp);
00060 static int sdp_append_connection (char *string, int size, char *tmp,
00061                                   sdp_connection_t * conn, char **next_tmp);
00062 
00063 int
00064 sdp_bandwidth_init (sdp_bandwidth_t ** b)
00065 {
00066   *b = (sdp_bandwidth_t *) osip_malloc (sizeof (sdp_bandwidth_t));
00067   if (*b == NULL)
00068     return -1;
00069   (*b)->b_bwtype = NULL;
00070   (*b)->b_bandwidth = NULL;
00071   return 0;
00072 }
00073 
00074 void
00075 sdp_bandwidth_free (sdp_bandwidth_t * b)
00076 {
00077   if (b == NULL)
00078     return;
00079   osip_free (b->b_bwtype);
00080   osip_free (b->b_bandwidth);
00081   osip_free (b);
00082 }
00083 
00084 int
00085 sdp_time_descr_init (sdp_time_descr_t ** td)
00086 {
00087   *td = (sdp_time_descr_t *) osip_malloc (sizeof (sdp_time_descr_t));
00088   if (*td == NULL)
00089     return -1;
00090   (*td)->t_start_time = NULL;
00091   (*td)->t_stop_time = NULL;
00092   (*td)->r_repeats = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
00093   osip_list_init ((*td)->r_repeats);
00094   return 0;
00095 }
00096 
00097 void
00098 sdp_time_descr_free (sdp_time_descr_t * td)
00099 {
00100   if (td == NULL)
00101     return;
00102   osip_free (td->t_start_time);
00103   osip_free (td->t_stop_time);
00104   osip_list_ofchar_free (td->r_repeats);
00105   osip_free (td);
00106 }
00107 
00108 int
00109 sdp_key_init (sdp_key_t ** key)
00110 {
00111   *key = (sdp_key_t *) osip_malloc (sizeof (sdp_key_t));
00112   if (*key == NULL)
00113     return -1;
00114   (*key)->k_keytype = NULL;
00115   (*key)->k_keydata = NULL;
00116   return 0;
00117 }
00118 
00119 void
00120 sdp_key_free (sdp_key_t * key)
00121 {
00122   if (key == NULL)
00123     return;
00124   osip_free (key->k_keytype);
00125   osip_free (key->k_keydata);
00126   osip_free (key);
00127 }
00128 
00129 int
00130 sdp_attribute_init (sdp_attribute_t ** attribute)
00131 {
00132   *attribute = (sdp_attribute_t *) osip_malloc (sizeof (sdp_attribute_t));
00133   if (*attribute == NULL)
00134     return -1;
00135   (*attribute)->a_att_field = NULL;
00136   (*attribute)->a_att_value = NULL;
00137   return 0;
00138 }
00139 
00140 void
00141 sdp_attribute_free (sdp_attribute_t * attribute)
00142 {
00143   if (attribute == NULL)
00144     return;
00145   osip_free (attribute->a_att_field);
00146   osip_free (attribute->a_att_value);
00147   osip_free (attribute);
00148 }
00149 
00150 int
00151 sdp_connection_init (sdp_connection_t ** connection)
00152 {
00153   *connection = (sdp_connection_t *) osip_malloc (sizeof (sdp_connection_t));
00154   if (*connection == NULL)
00155     return -1;
00156   (*connection)->c_nettype = NULL;
00157   (*connection)->c_addrtype = NULL;
00158   (*connection)->c_addr = NULL;
00159   (*connection)->c_addr_multicast_ttl = NULL;
00160   (*connection)->c_addr_multicast_int = NULL;
00161   return 0;
00162 }
00163 
00164 void
00165 sdp_connection_free (sdp_connection_t * connection)
00166 {
00167   if (connection == NULL)
00168     return;
00169   osip_free (connection->c_nettype);
00170   osip_free (connection->c_addrtype);
00171   osip_free (connection->c_addr);
00172   osip_free (connection->c_addr_multicast_ttl);
00173   osip_free (connection->c_addr_multicast_int);
00174   osip_free (connection);
00175 }
00176 
00177 int
00178 sdp_media_init (sdp_media_t ** media)
00179 {
00180   *media = (sdp_media_t *) osip_malloc (sizeof (sdp_media_t));
00181   if (*media == NULL)
00182     return -1;
00183   (*media)->m_media = NULL;
00184   (*media)->m_port = NULL;
00185   (*media)->m_number_of_port = NULL;
00186   (*media)->m_proto = NULL;
00187   (*media)->m_payloads = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
00188   osip_list_init ((*media)->m_payloads);
00189   (*media)->i_info = NULL;
00190   (*media)->c_connections = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
00191   osip_list_init ((*media)->c_connections);
00192   (*media)->b_bandwidths = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
00193   osip_list_init ((*media)->b_bandwidths);
00194   (*media)->a_attributes = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
00195   osip_list_init ((*media)->a_attributes);
00196   (*media)->k_key = NULL;
00197   return 0;
00198 }
00199 
00200 void
00201 sdp_media_free (sdp_media_t * media)
00202 {
00203   if (media == NULL)
00204     return;
00205   osip_free (media->m_media);
00206   osip_free (media->m_port);
00207   osip_free (media->m_number_of_port);
00208   osip_free (media->m_proto);
00209   osip_list_ofchar_free (media->m_payloads);
00210   osip_free (media->i_info);
00211   osip_list_special_free (media->c_connections,
00212                           (void *(*)(void *)) &sdp_connection_free);
00213   osip_list_special_free (media->b_bandwidths,
00214                           (void *(*)(void *)) &sdp_bandwidth_free);
00215   osip_list_special_free (media->a_attributes,
00216                           (void *(*)(void *)) &sdp_attribute_free);
00217   sdp_key_free (media->k_key);
00218   osip_free (media);
00219 }
00220 
00221 /* to be changed to sdp_message_init(sdp_message_t **dest) */
00222 int
00223 sdp_message_init (sdp_message_t ** sdp)
00224 {
00225   (*sdp) = (sdp_message_t *) osip_malloc (sizeof (sdp_message_t));
00226   if (*sdp == NULL)
00227     return -1;
00228 
00229   (*sdp)->v_version = NULL;
00230   (*sdp)->o_username = NULL;
00231   (*sdp)->o_sess_id = NULL;
00232   (*sdp)->o_sess_version = NULL;
00233   (*sdp)->o_nettype = NULL;
00234   (*sdp)->o_addrtype = NULL;
00235   (*sdp)->o_addr = NULL;
00236   (*sdp)->s_name = NULL;
00237   (*sdp)->i_info = NULL;
00238   (*sdp)->u_uri = NULL;
00239 
00240   (*sdp)->e_emails = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
00241   if ((*sdp)->e_emails == NULL)
00242     return -1;
00243   osip_list_init ((*sdp)->e_emails);
00244 
00245   (*sdp)->p_phones = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
00246   if ((*sdp)->p_phones == NULL)
00247     return -1;
00248   osip_list_init ((*sdp)->p_phones);
00249 
00250   (*sdp)->c_connection = NULL;
00251 
00252   (*sdp)->b_bandwidths = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
00253   if ((*sdp)->b_bandwidths == NULL)
00254     return -1;
00255   osip_list_init ((*sdp)->b_bandwidths);
00256 
00257   (*sdp)->t_descrs = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
00258   if ((*sdp)->t_descrs == NULL)
00259     return -1;
00260   osip_list_init ((*sdp)->t_descrs);
00261 
00262   (*sdp)->z_adjustments = NULL;
00263   (*sdp)->k_key = NULL;
00264 
00265   (*sdp)->a_attributes = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
00266   if ((*sdp)->a_attributes == NULL)
00267     return -1;
00268   osip_list_init ((*sdp)->a_attributes);
00269 
00270   (*sdp)->m_medias = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
00271   if ((*sdp)->m_medias == NULL)
00272     return -1;
00273   osip_list_init ((*sdp)->m_medias);
00274   return 0;
00275 }
00276 
00277 static int
00278 sdp_message_parse_v (sdp_message_t * sdp, char *buf, char **next)
00279 {
00280   char *equal;
00281   char *crlf;
00282 
00283   *next = buf;
00284 
00285   equal = buf;
00286   while ((*equal != '=') && (*equal != '\0'))
00287     equal++;
00288   if (*equal == '\0')
00289     return ERR_ERROR;
00290 
00291   if (equal == buf)
00292     return ERR_DISCARD;
00293 
00294   /* check if header is "v" */
00295   if (equal[-1] != 'v')
00296     return ERR_DISCARD;
00297 
00298   crlf = equal + 1;
00299 
00300   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00301     crlf++;
00302   if (*crlf == '\0')
00303     return ERR_ERROR;
00304   if (crlf == equal + 1)
00305     return ERR_ERROR;           /*v=\r ?? bad header */
00306   sdp->v_version = osip_malloc (crlf - (equal + 1) + 1);
00307   osip_strncpy (sdp->v_version, equal + 1, crlf - (equal + 1));
00308 
00309   if (crlf[1] == '\n')
00310     *next = crlf + 2;
00311   else
00312     *next = crlf + 1;
00313   return WF;
00314 }
00315 
00316 static int
00317 sdp_message_parse_o (sdp_message_t * sdp, char *buf, char **next)
00318 {
00319   char *equal;
00320   char *crlf;
00321   char *tmp;
00322   char *tmp_next;
00323   int i;
00324 
00325   *next = buf;
00326 
00327   equal = buf;
00328   while ((*equal != '=') && (*equal != '\0'))
00329     equal++;
00330   if (*equal == '\0')
00331     return ERR_ERROR;
00332 
00333   /* check if header is "o" */
00334   if (equal[-1] != 'o')
00335     return ERR_DISCARD;
00336 
00337   crlf = equal + 1;
00338 
00339   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00340     crlf++;
00341   if (*crlf == '\0')
00342     return ERR_ERROR;
00343   if (crlf == equal + 1)
00344     return ERR_ERROR;           /* o=\r ?? bad header */
00345 
00346   tmp = equal + 1;
00347   /* o=username sess-id sess-version nettype addrtype addr */
00348 
00349   /* useranme can contain any char (ascii) except "space" and CRLF */
00350 #ifdef FIREFLY_BUG_SUPPORT
00351   if (tmp[0] == ' ')
00352     {
00353       sdp->o_username = osip_strdup ("firefly");
00354       tmp++;
00355   } else
00356     {
00357       i = __osip_set_next_token (&(sdp->o_username), tmp, ' ', &tmp_next);
00358       if (i != 0)
00359         return -1;
00360       tmp = tmp_next;
00361     }
00362 #else
00363   i = __osip_set_next_token (&(sdp->o_username), tmp, ' ', &tmp_next);
00364   if (i != 0)
00365     return -1;
00366   tmp = tmp_next;
00367 #endif
00368 
00369   /* sess_id contains only numeric characters */
00370   i = __osip_set_next_token (&(sdp->o_sess_id), tmp, ' ', &tmp_next);
00371   if (i != 0)
00372     return -1;
00373   tmp = tmp_next;
00374 
00375   /* sess_id contains only numeric characters */
00376   i = __osip_set_next_token (&(sdp->o_sess_version), tmp, ' ', &tmp_next);
00377   if (i != 0)
00378     return -1;
00379   tmp = tmp_next;
00380 
00381   /* nettype is "IN" but will surely be extented!!! assume it's some alpha-char */
00382   i = __osip_set_next_token (&(sdp->o_nettype), tmp, ' ', &tmp_next);
00383   if (i != 0)
00384     return -1;
00385   tmp = tmp_next;
00386 
00387   /* addrtype  is "IP4" or "IP6" but will surely be extented!!! */
00388   i = __osip_set_next_token (&(sdp->o_addrtype), tmp, ' ', &tmp_next);
00389   if (i != 0)
00390     return -1;
00391   tmp = tmp_next;
00392 
00393   /* addr  is "IP4" or "IP6" but will surely be extented!!! */
00394   i = __osip_set_next_token (&(sdp->o_addr), tmp, '\r', &tmp_next);
00395   if (i != 0)
00396     {                           /* could it be "\n" only??? rfc says to accept CR or LF instead of CRLF */
00397       i = __osip_set_next_token (&(sdp->o_addr), tmp, '\n', &tmp_next);
00398       if (i != 0)
00399         return -1;
00400     }
00401 
00402   if (crlf[1] == '\n')
00403     *next = crlf + 2;
00404   else
00405     *next = crlf + 1;
00406   return WF;
00407 }
00408 
00409 static int
00410 sdp_message_parse_s (sdp_message_t * sdp, char *buf, char **next)
00411 {
00412   char *equal;
00413   char *crlf;
00414 
00415   *next = buf;
00416 
00417   equal = buf;
00418   while ((*equal != '=') && (*equal != '\0'))
00419     equal++;
00420   if (*equal == '\0')
00421     return ERR_ERROR;
00422 
00423   /* check if header is "s" */
00424   if (equal[-1] != 's')
00425     return ERR_DISCARD;
00426 
00427   crlf = equal + 1;
00428 
00429   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00430     crlf++;
00431   if (*crlf == '\0')
00432     return ERR_ERROR;
00433 #ifdef FIREFLY_BUG_SUPPORT
00434   if (crlf == equal + 1)
00435     {
00436       sdp->s_name = osip_strdup (" ");
00437       if (crlf[1] == '\n')
00438         *next = crlf + 2;
00439       else
00440         *next = crlf + 1;
00441       return WF;                /* o=\r ?? bad header */
00442     }
00443 #else
00444   if (crlf == equal + 1)
00445     return ERR_ERROR;           /* o=\r ?? bad header */
00446 #endif
00447 
00448   /* s=text */
00449 
00450   /* text is interpreted as ISO-10646 UTF8! */
00451   /* using ISO 8859-1 requires "a=charset:ISO-8859-1 */
00452   sdp->s_name = osip_malloc (crlf - (equal + 1) + 1);
00453   osip_strncpy (sdp->s_name, equal + 1, crlf - (equal + 1));
00454 
00455   if (crlf[1] == '\n')
00456     *next = crlf + 2;
00457   else
00458     *next = crlf + 1;
00459   return WF;
00460 }
00461 
00462 static int
00463 sdp_message_parse_i (sdp_message_t * sdp, char *buf, char **next)
00464 {
00465   char *equal;
00466   char *crlf;
00467   int i;
00468   char *i_info;
00469 
00470   *next = buf;
00471 
00472   equal = buf;
00473   while ((*equal != '=') && (*equal != '\0'))
00474     equal++;
00475   if (*equal == '\0')
00476     return ERR_ERROR;
00477 
00478   /* check if header is "i" */
00479   if (equal[-1] != 'i')
00480     return ERR_DISCARD;
00481 
00482   crlf = equal + 1;
00483 
00484   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00485     crlf++;
00486   if (*crlf == '\0')
00487     return ERR_ERROR;
00488   if (crlf == equal + 1)
00489     return ERR_ERROR;           /* o=\r ?? bad header */
00490 
00491   /* s=text */
00492 
00493   /* text is interpreted as ISO-10646 UTF8! */
00494   /* using ISO 8859-1 requires "a=charset:ISO-8859-1 */
00495   i_info = osip_malloc (crlf - (equal + 1) + 1);
00496   osip_strncpy (i_info, equal + 1, crlf - (equal + 1));
00497 
00498   /* add the bandwidth at the correct place:
00499      if there is no media line yet, then the "b=" is the
00500      global one.
00501    */
00502   i = osip_list_size (sdp->m_medias);
00503   if (i == 0)
00504     sdp->i_info = i_info;
00505   else
00506     {
00507       sdp_media_t *last_sdp_media =
00508         (sdp_media_t *) osip_list_get (sdp->m_medias, i - 1);
00509       last_sdp_media->i_info = i_info;
00510     }
00511 
00512   if (crlf[1] == '\n')
00513     *next = crlf + 2;
00514   else
00515     *next = crlf + 1;
00516   return WF;
00517 }
00518 
00519 static int
00520 sdp_message_parse_u (sdp_message_t * sdp, char *buf, char **next)
00521 {
00522   char *equal;
00523   char *crlf;
00524 
00525   *next = buf;
00526 
00527   equal = buf;
00528   while ((*equal != '=') && (*equal != '\0'))
00529     equal++;
00530   if (*equal == '\0')
00531     return ERR_ERROR;
00532 
00533   /* check if header is "u" */
00534   if (equal[-1] != 'u')
00535     return ERR_DISCARD;
00536 
00537   crlf = equal + 1;
00538 
00539   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00540     crlf++;
00541   if (*crlf == '\0')
00542     return ERR_ERROR;
00543   if (crlf == equal + 1)
00544     return ERR_ERROR;           /* u=\r ?? bad header */
00545 
00546   /* u=uri */
00547   /* we assume this is a URI */
00548   sdp->u_uri = osip_malloc (crlf - (equal + 1) + 1);
00549   osip_strncpy (sdp->u_uri, equal + 1, crlf - (equal + 1));
00550 
00551   if (crlf[1] == '\n')
00552     *next = crlf + 2;
00553   else
00554     *next = crlf + 1;
00555   return WF;
00556 }
00557 
00558 static int
00559 sdp_message_parse_e (sdp_message_t * sdp, char *buf, char **next)
00560 {
00561   char *equal;
00562   char *crlf;
00563   char *e_email;
00564 
00565   *next = buf;
00566 
00567   equal = buf;
00568   while ((*equal != '=') && (*equal != '\0'))
00569     equal++;
00570   if (*equal == '\0')
00571     return ERR_ERROR;
00572 
00573   /* check if header is "e" */
00574   if (equal[-1] != 'e')
00575     return ERR_DISCARD;
00576 
00577   crlf = equal + 1;
00578 
00579   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00580     crlf++;
00581   if (*crlf == '\0')
00582     return ERR_ERROR;
00583   if (crlf == equal + 1)
00584     return ERR_ERROR;           /* e=\r ?? bad header */
00585 
00586   /* e=email */
00587   /* we assume this is an EMAIL-ADDRESS */
00588   e_email = osip_malloc (crlf - (equal + 1) + 1);
00589   osip_strncpy (e_email, equal + 1, crlf - (equal + 1));
00590 
00591   osip_list_add (sdp->e_emails, e_email, -1);
00592 
00593   if (crlf[1] == '\n')
00594     *next = crlf + 2;
00595   else
00596     *next = crlf + 1;
00597   return WF;
00598 }
00599 
00600 static int
00601 sdp_message_parse_p (sdp_message_t * sdp, char *buf, char **next)
00602 {
00603   char *equal;
00604   char *crlf;
00605   char *p_phone;
00606 
00607   *next = buf;
00608 
00609   equal = buf;
00610   while ((*equal != '=') && (*equal != '\0'))
00611     equal++;
00612   if (*equal == '\0')
00613     return ERR_ERROR;
00614 
00615   /* check if header is "p" */
00616   if (equal[-1] != 'p')
00617     return ERR_DISCARD;
00618 
00619   crlf = equal + 1;
00620 
00621   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00622     crlf++;
00623   if (*crlf == '\0')
00624     return ERR_ERROR;
00625   if (crlf == equal + 1)
00626     return ERR_ERROR;           /* p=\r ?? bad header */
00627 
00628   /* e=email */
00629   /* we assume this is an EMAIL-ADDRESS */
00630   p_phone = osip_malloc (crlf - (equal + 1) + 1);
00631   osip_strncpy (p_phone, equal + 1, crlf - (equal + 1));
00632 
00633   osip_list_add (sdp->p_phones, p_phone, -1);
00634 
00635   if (crlf[1] == '\n')
00636     *next = crlf + 2;
00637   else
00638     *next = crlf + 1;
00639   return WF;
00640 }
00641 
00642 static int
00643 sdp_message_parse_c (sdp_message_t * sdp, char *buf, char **next)
00644 {
00645   char *equal;
00646   char *crlf;
00647   char *tmp;
00648   char *tmp_next;
00649   sdp_connection_t *c_header;
00650   int i;
00651 
00652   *next = buf;
00653 
00654   equal = buf;
00655   while ((*equal != '=') && (*equal != '\0'))
00656     equal++;
00657   if (*equal == '\0')
00658     return ERR_ERROR;
00659 
00660   /* check if header is "c" */
00661   if (equal[-1] != 'c')
00662     return ERR_DISCARD;
00663 
00664   crlf = equal + 1;
00665 
00666   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00667     crlf++;
00668   if (*crlf == '\0')
00669     return ERR_ERROR;
00670   if (crlf == equal + 1)
00671     return ERR_ERROR;           /* c=\r ?? bad header */
00672 
00673   tmp = equal + 1;
00674   i = sdp_connection_init (&c_header);
00675   if (i != 0)
00676     return ERR_ERROR;
00677   /* c=nettype addrtype (multicastaddr | addr) */
00678 
00679   /* nettype is "IN" and will be extended */
00680   i = __osip_set_next_token (&(c_header->c_nettype), tmp, ' ', &tmp_next);
00681   if (i != 0)
00682     return -1;
00683   tmp = tmp_next;
00684 
00685   /* nettype is "IP4" or "IP6" and will be extended */
00686   i = __osip_set_next_token (&(c_header->c_addrtype), tmp, ' ', &tmp_next);
00687   if (i != 0)
00688     return -1;
00689   tmp = tmp_next;
00690 
00691   /* there we have a multicast or unicast address */
00692   /* multicast can be ip/ttl [/integer] */
00693   /* unicast is FQDN or ip (no ttl, no integer) */
00694 
00695   /* is MULTICAST? */
00696   {
00697     char *slash = strchr (tmp, '/');
00698 
00699     if (slash != NULL && slash < crlf)  /* it's a multicast address! */
00700       {
00701         i = __osip_set_next_token (&(c_header->c_addr), tmp, '/', &tmp_next);
00702         if (i != 0)
00703           return -1;
00704         tmp = tmp_next;
00705         slash = strchr (slash + 1, '/');
00706         if (slash != NULL && slash < crlf)      /* optionnal integer is there! */
00707           {
00708             i =
00709               __osip_set_next_token (&(c_header->c_addr_multicast_ttl), tmp,
00710                                      '/', &tmp_next);
00711             if (i != 0)
00712               return -1;
00713             tmp = tmp_next;
00714             i =
00715               __osip_set_next_token (&(c_header->c_addr_multicast_int), tmp,
00716                                      '\r', &tmp_next);
00717             if (i != 0)
00718               {
00719                 i =
00720                   __osip_set_next_token (&(c_header->c_addr_multicast_int),
00721                                          tmp, '\n', &tmp_next);
00722                 if (i != 0)
00723                   {
00724                     sdp_connection_free (c_header);
00725                     return -1;
00726                   }
00727               }
00728         } else
00729           {
00730             i =
00731               __osip_set_next_token (&(c_header->c_addr_multicast_ttl), tmp,
00732                                      '\r', &tmp_next);
00733             if (i != 0)
00734               {
00735                 i =
00736                   __osip_set_next_token (&(c_header->c_addr_multicast_ttl),
00737                                          tmp, '\n', &tmp_next);
00738                 if (i != 0)
00739                   {
00740                     sdp_connection_free (c_header);
00741                     return -1;
00742                   }
00743               }
00744           }
00745     } else
00746       {
00747         /* in this case, we have a unicast address */
00748         i = __osip_set_next_token (&(c_header->c_addr), tmp, '\r', &tmp_next);
00749         if (i != 0)
00750           {
00751             i = __osip_set_next_token (&(c_header->c_addr), tmp, '\n', &tmp_next);
00752             if (i != 0)
00753               {
00754                 sdp_connection_free (c_header);
00755                 return -1;
00756               }
00757           }
00758       }
00759   }
00760 
00761   /* add the connection at the correct place:
00762      if there is no media line yet, then the "c=" is the
00763      global one.
00764    */
00765   i = osip_list_size (sdp->m_medias);
00766   if (i == 0)
00767     sdp->c_connection = c_header;
00768   else
00769     {
00770       sdp_media_t *last_sdp_media =
00771         (sdp_media_t *) osip_list_get (sdp->m_medias, i - 1);
00772       osip_list_add (last_sdp_media->c_connections, c_header, -1);
00773     }
00774   if (crlf[1] == '\n')
00775     *next = crlf + 2;
00776   else
00777     *next = crlf + 1;
00778   return WF;
00779 }
00780 
00781 static int
00782 sdp_message_parse_b (sdp_message_t * sdp, char *buf, char **next)
00783 {
00784   char *equal;
00785   char *crlf;
00786   char *tmp;
00787   char *tmp_next;
00788   int i;
00789   sdp_bandwidth_t *b_header;
00790 
00791   *next = buf;
00792 
00793   equal = buf;
00794   while ((*equal != '=') && (*equal != '\0'))
00795     equal++;
00796   if (*equal == '\0')
00797     return ERR_ERROR;
00798 
00799   /* check if header is "b" */
00800   if (equal[-1] != 'b')
00801     return ERR_DISCARD;
00802 
00803   crlf = equal + 1;
00804 
00805   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00806     crlf++;
00807   if (*crlf == '\0')
00808     return ERR_ERROR;
00809   if (crlf == equal + 1)
00810     return ERR_ERROR;           /* b=\r ?? bad header */
00811 
00812   tmp = equal + 1;
00813   /* b = bwtype: bandwidth */
00814   i = sdp_bandwidth_init (&b_header);
00815   if (i != 0)
00816     return ERR_ERROR;
00817 
00818   /* bwtype is alpha-numeric */
00819   i = __osip_set_next_token (&(b_header->b_bwtype), tmp, ':', &tmp_next);
00820   if (i != 0)
00821     return -1;
00822   tmp = tmp_next;
00823 
00824   i = __osip_set_next_token (&(b_header->b_bandwidth), tmp, '\r', &tmp_next);
00825   if (i != 0)
00826     {
00827       i = __osip_set_next_token (&(b_header->b_bandwidth), tmp, '\n', &tmp_next);
00828       if (i != 0)
00829         {
00830           sdp_bandwidth_free (b_header);
00831           return -1;
00832         }
00833     }
00834 
00835   /* add the bandwidth at the correct place:
00836      if there is no media line yet, then the "b=" is the
00837      global one.
00838    */
00839   i = osip_list_size (sdp->m_medias);
00840   if (i == 0)
00841     osip_list_add (sdp->b_bandwidths, b_header, -1);
00842   else
00843     {
00844       sdp_media_t *last_sdp_media =
00845         (sdp_media_t *) osip_list_get (sdp->m_medias, i - 1);
00846       osip_list_add (last_sdp_media->b_bandwidths, b_header, -1);
00847     }
00848 
00849   if (crlf[1] == '\n')
00850     *next = crlf + 2;
00851   else
00852     *next = crlf + 1;
00853   return WF;
00854 }
00855 
00856 static int
00857 sdp_message_parse_t (sdp_message_t * sdp, char *buf, char **next)
00858 {
00859   char *equal;
00860   char *crlf;
00861   char *tmp;
00862   char *tmp_next;
00863   int i;
00864   sdp_time_descr_t *t_header;
00865 
00866   *next = buf;
00867 
00868   equal = buf;
00869   while ((*equal != '=') && (*equal != '\0'))
00870     equal++;
00871   if (*equal == '\0')
00872     return ERR_ERROR;
00873 
00874   /* check if header is "t" */
00875   if (equal[-1] != 't')
00876     return ERR_DISCARD;
00877 
00878   crlf = equal + 1;
00879 
00880   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00881     crlf++;
00882   if (*crlf == '\0')
00883     return ERR_ERROR;
00884   if (crlf == equal + 1)
00885     return ERR_ERROR;           /* t=\r ?? bad header */
00886 
00887   tmp = equal + 1;
00888   /* t = start_time stop_time */
00889   i = sdp_time_descr_init (&t_header);
00890   if (i != 0)
00891     return ERR_ERROR;
00892 
00893   i = __osip_set_next_token (&(t_header->t_start_time), tmp, ' ', &tmp_next);
00894   if (i != 0)
00895     {
00896       sdp_time_descr_free (t_header);
00897       return -1;
00898     }
00899   tmp = tmp_next;
00900 
00901   i = __osip_set_next_token (&(t_header->t_stop_time), tmp, '\r', &tmp_next);
00902   if (i != 0)
00903     {
00904       i = __osip_set_next_token (&(t_header->t_stop_time), tmp, '\n', &tmp_next);
00905       if (i != 0)
00906         {
00907           sdp_time_descr_free (t_header);
00908           return -1;
00909         }
00910     }
00911 
00912   /* add the new time_description header */
00913   osip_list_add (sdp->t_descrs, t_header, -1);
00914 
00915   if (crlf[1] == '\n')
00916     *next = crlf + 2;
00917   else
00918     *next = crlf + 1;
00919   return WF;
00920 }
00921 
00922 static int
00923 sdp_message_parse_r (sdp_message_t * sdp, char *buf, char **next)
00924 {
00925   char *equal;
00926   char *crlf;
00927   int index;
00928   char *r_header;
00929   sdp_time_descr_t *t_descr;
00930 
00931   *next = buf;
00932 
00933   equal = buf;
00934   while ((*equal != '=') && (*equal != '\0'))
00935     equal++;
00936   if (*equal == '\0')
00937     return ERR_ERROR;
00938 
00939   /* check if header is "r" */
00940   if (equal[-1] != 'r')
00941     return ERR_DISCARD;
00942 
00943   index = osip_list_size (sdp->t_descrs);
00944   if (index == 0)
00945     return ERR_ERROR;           /* r field can't come alone! */
00946 
00947   crlf = equal + 1;
00948 
00949   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00950     crlf++;
00951   if (*crlf == '\0')
00952     return ERR_ERROR;
00953   if (crlf == equal + 1)
00954     return ERR_ERROR;           /* r=\r ?? bad header */
00955 
00956   /* r=far too complexe and somewhat useless... I don't parse it! */
00957   r_header = osip_malloc (crlf - (equal + 1) + 1);
00958   osip_strncpy (r_header, equal + 1, crlf - (equal + 1));
00959 
00960   /* r field carry information for the last "t" field */
00961   t_descr = (sdp_time_descr_t *) osip_list_get (sdp->t_descrs, index - 1);
00962   osip_list_add (t_descr->r_repeats, r_header, -1);
00963 
00964   if (crlf[1] == '\n')
00965     *next = crlf + 2;
00966   else
00967     *next = crlf + 1;
00968   return WF;
00969 }
00970 
00971 static int
00972 sdp_message_parse_z (sdp_message_t * sdp, char *buf, char **next)
00973 {
00974   char *equal;
00975   char *crlf;
00976   char *z_header;
00977 
00978   *next = buf;
00979 
00980   equal = buf;
00981   while ((*equal != '=') && (*equal != '\0'))
00982     equal++;
00983   if (*equal == '\0')
00984     return ERR_ERROR;
00985 
00986   /* check if header is "z" */
00987   if (equal[-1] != 'z')
00988     return ERR_DISCARD;
00989 
00990   crlf = equal + 1;
00991 
00992   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
00993     crlf++;
00994   if (*crlf == '\0')
00995     return ERR_ERROR;
00996   if (crlf == equal + 1)
00997     return ERR_ERROR;           /* z=\r ?? bad header */
00998 
00999   /* z=somewhat useless... I don't parse it! */
01000   z_header = osip_malloc (crlf - (equal + 1) + 1);
01001   osip_strncpy (z_header, equal + 1, crlf - (equal + 1));
01002 
01003   sdp->z_adjustments = z_header;
01004 
01005   if (crlf[1] == '\n')
01006     *next = crlf + 2;
01007   else
01008     *next = crlf + 1;
01009   return WF;
01010 }
01011 
01012 static int
01013 sdp_message_parse_k (sdp_message_t * sdp, char *buf, char **next)
01014 {
01015   char *equal;
01016   char *crlf;
01017   int i;
01018   char *colon;
01019   sdp_key_t *k_header;
01020   char *tmp;
01021   char *tmp_next;
01022 
01023   *next = buf;
01024 
01025   equal = buf;
01026   while ((*equal != '=') && (*equal != '\0'))
01027     equal++;
01028   if (*equal == '\0')
01029     return ERR_ERROR;
01030 
01031   /* check if header is "k" */
01032   if (equal[-1] != 'k')
01033     return ERR_DISCARD;
01034 
01035   crlf = equal + 1;
01036 
01037   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
01038     crlf++;
01039   if (*crlf == '\0')
01040     return ERR_ERROR;
01041   if (crlf == equal + 1)
01042     return ERR_ERROR;           /* k=\r ?? bad header */
01043 
01044   tmp = equal + 1;
01045 
01046   i = sdp_key_init (&k_header);
01047   if (i != 0)
01048     return ERR_ERROR;
01049   /* k=key-type[:key-data] */
01050 
01051   /* is there any key-data? */
01052   colon = strchr (equal + 1, ':');
01053   if ((colon != NULL) && (colon < crlf))
01054     {
01055       /* att-field is alpha-numeric */
01056       i = __osip_set_next_token (&(k_header->k_keytype), tmp, ':', &tmp_next);
01057       if (i != 0)
01058         {
01059           sdp_key_free (k_header);
01060           return -1;
01061         }
01062       tmp = tmp_next;
01063 
01064       i = __osip_set_next_token (&(k_header->k_keydata), tmp, '\r', &tmp_next);
01065       if (i != 0)
01066         {
01067           i = __osip_set_next_token (&(k_header->k_keydata), tmp, '\n', &tmp_next);
01068           if (i != 0)
01069             {
01070               sdp_key_free (k_header);
01071               return -1;
01072             }
01073         }
01074   } else
01075     {
01076       i = __osip_set_next_token (&(k_header->k_keytype), tmp, '\r', &tmp_next);
01077       if (i != 0)
01078         {
01079           i = __osip_set_next_token (&(k_header->k_keytype), tmp, '\n', &tmp_next);
01080           if (i != 0)
01081             {
01082               sdp_key_free (k_header);
01083               return -1;
01084             }
01085         }
01086     }
01087 
01088   /* add the key at the correct place:
01089      if there is no media line yet, then the "k=" is the
01090      global one.
01091    */
01092   i = osip_list_size (sdp->m_medias);
01093   if (i == 0)
01094     sdp->k_key = k_header;
01095   else
01096     {
01097       sdp_media_t *last_sdp_media =
01098         (sdp_media_t *) osip_list_get (sdp->m_medias, i - 1);
01099       last_sdp_media->k_key = k_header;
01100     }
01101 
01102   if (crlf[1] == '\n')
01103     *next = crlf + 2;
01104   else
01105     *next = crlf + 1;
01106   return WF;
01107 }
01108 
01109 static int
01110 sdp_message_parse_a (sdp_message_t * sdp, char *buf, char **next)
01111 {
01112   char *equal;
01113   char *crlf;
01114   char *tmp;
01115   char *tmp_next;
01116   int i;
01117   sdp_attribute_t *a_attribute;
01118   char *colon;
01119 
01120   *next = buf;
01121 
01122   equal = buf;
01123   while ((*equal != '=') && (*equal != '\0'))
01124     equal++;
01125   if (*equal == '\0')
01126     return ERR_ERROR;
01127 
01128   /* check if header is "a" */
01129   if (equal[-1] != 'a')
01130     return ERR_DISCARD;
01131 
01132   crlf = equal + 1;
01133 
01134   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
01135     crlf++;
01136   if (*crlf == '\0')
01137     return ERR_ERROR;
01138   if (crlf == equal + 1)
01139     return ERR_ERROR;           /* a=\r ?? bad header */
01140 
01141   tmp = equal + 1;
01142 
01143   i = sdp_attribute_init (&a_attribute);
01144   if (i != 0)
01145     return ERR_ERROR;
01146 
01147   /* a=att-field[:att-value] */
01148 
01149   /* is there any att-value? */
01150   colon = strchr (equal + 1, ':');
01151   if ((colon != NULL) && (colon < crlf))
01152     {
01153       /* att-field is alpha-numeric */
01154       i = __osip_set_next_token (&(a_attribute->a_att_field), tmp, ':', &tmp_next);
01155       if (i != 0)
01156         {
01157           sdp_attribute_free (a_attribute);
01158           return -1;
01159         }
01160       tmp = tmp_next;
01161 
01162       i =
01163         __osip_set_next_token (&(a_attribute->a_att_value), tmp, '\r', &tmp_next);
01164       if (i != 0)
01165         {
01166           i =
01167             __osip_set_next_token (&(a_attribute->a_att_value), tmp, '\n',
01168                                    &tmp_next);
01169           if (i != 0)
01170             {
01171               sdp_attribute_free (a_attribute);
01172               return -1;
01173             }
01174         }
01175   } else
01176     {
01177       i =
01178         __osip_set_next_token (&(a_attribute->a_att_field), tmp, '\r', &tmp_next);
01179       if (i != 0)
01180         {
01181           i =
01182             __osip_set_next_token (&(a_attribute->a_att_field), tmp, '\n',
01183                                    &tmp_next);
01184           if (i != 0)
01185             {
01186               sdp_attribute_free (a_attribute);
01187               return -1;
01188             }
01189         }
01190     }
01191 
01192   /* add the attribute at the correct place:
01193      if there is no media line yet, then the "a=" is the
01194      global one.
01195    */
01196   i = osip_list_size (sdp->m_medias);
01197   if (i == 0)
01198     osip_list_add (sdp->a_attributes, a_attribute, -1);
01199   else
01200     {
01201       sdp_media_t *last_sdp_media =
01202         (sdp_media_t *) osip_list_get (sdp->m_medias, i - 1);
01203       osip_list_add (last_sdp_media->a_attributes, a_attribute, -1);
01204     }
01205 
01206   if (crlf[1] == '\n')
01207     *next = crlf + 2;
01208   else
01209     *next = crlf + 1;
01210   return WF;
01211 }
01212 
01213 static int
01214 sdp_message_parse_m (sdp_message_t * sdp, char *buf, char **next)
01215 {
01216   char *equal;
01217   char *crlf;
01218   char *tmp;
01219   char *tmp_next;
01220   int i;
01221   sdp_media_t *m_header;
01222   char *slash;
01223   char *space;
01224 
01225   *next = buf;
01226 
01227   equal = buf;
01228   while ((*equal != '=') && (*equal != '\0'))
01229     equal++;
01230   if (*equal == '\0')
01231     return ERR_ERROR;
01232 
01233   /* check if header is "m" */
01234   if (equal[-1] != 'm')
01235     return ERR_DISCARD;
01236 
01237   crlf = equal + 1;
01238 
01239   while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0'))
01240     crlf++;
01241   if (*crlf == '\0')
01242     return ERR_ERROR;
01243   if (crlf == equal + 1)
01244     return ERR_ERROR;           /* a=\r ?? bad header */
01245 
01246   tmp = equal + 1;
01247 
01248   i = sdp_media_init (&m_header);
01249   if (i != 0)
01250     return ERR_ERROR;
01251 
01252   /* m=media port ["/"integer] proto *(payload_number) */
01253 
01254   /* media is "audio" "video" "application" "data" or other... */
01255   i = __osip_set_next_token (&(m_header->m_media), tmp, ' ', &tmp_next);
01256   if (i != 0)
01257     {
01258       sdp_media_free (m_header);
01259       return -1;
01260     }
01261   tmp = tmp_next;
01262 
01263   slash = strchr (tmp, '/');
01264   space = strchr (tmp, ' ');
01265   if (space == NULL)            /* not possible! */
01266     {
01267       sdp_media_free (m_header);
01268       return ERR_ERROR;
01269     }
01270   if ((slash != NULL) && (slash < space))
01271     {                           /* a number of port is specified! */
01272       i = __osip_set_next_token (&(m_header->m_port), tmp, '/', &tmp_next);
01273       if (i != 0)
01274         {
01275           sdp_media_free (m_header);
01276           return -1;
01277         }
01278       tmp = tmp_next;
01279 
01280       i =
01281         __osip_set_next_token (&(m_header->m_number_of_port), tmp, ' ', &tmp_next);
01282       if (i != 0)
01283         {
01284           sdp_media_free (m_header);
01285           return -1;
01286         }
01287       tmp = tmp_next;
01288   } else
01289     {
01290       i = __osip_set_next_token (&(m_header->m_port), tmp, ' ', &tmp_next);
01291       if (i != 0)
01292         {
01293           sdp_media_free (m_header);
01294           return -1;
01295         }
01296       tmp = tmp_next;
01297     }
01298 
01299   i = __osip_set_next_token (&(m_header->m_proto), tmp, ' ', &tmp_next);
01300   if (i != 0)
01301     {
01302       sdp_media_free (m_header);
01303       return -1;
01304     }
01305   tmp = tmp_next;
01306 
01307   {
01308     char *str;
01309     int more_space_before_crlf;
01310 
01311     space = strchr (tmp + 1, ' ');
01312     if (space == NULL)
01313       more_space_before_crlf = 1;
01314     else if ((space != NULL) && (space > crlf))
01315       more_space_before_crlf = 1;
01316     else
01317       more_space_before_crlf = 0;
01318     while (more_space_before_crlf == 0)
01319       {
01320         i = __osip_set_next_token (&str, tmp, ' ', &tmp_next);
01321         if (i != 0)
01322           {
01323             sdp_media_free (m_header);
01324             return -1;
01325           }
01326         tmp = tmp_next;
01327         osip_list_add (m_header->m_payloads, str, -1);
01328 
01329         space = strchr (tmp + 1, ' ');
01330         if (space == NULL)
01331           more_space_before_crlf = 1;
01332         else if ((space != NULL) && (space > crlf))
01333           more_space_before_crlf = 1;
01334         else
01335           more_space_before_crlf = 0;
01336       }
01337     if (tmp_next < crlf)
01338       {                         /* tmp_next is still less than clrf: no space */
01339         i = __osip_set_next_token (&str, tmp, '\r', &tmp_next);
01340         if (i != 0)
01341           {
01342             i = __osip_set_next_token (&str, tmp, '\n', &tmp_next);
01343             if (i != 0)
01344               {
01345                 sdp_media_free (m_header);
01346                 return -1;
01347               }
01348           }
01349         osip_list_add (m_header->m_payloads, str, -1);
01350       }
01351   }
01352 
01353   osip_list_add (sdp->m_medias, m_header, -1);
01354 
01355   if (crlf[1] == '\n')
01356     *next = crlf + 2;
01357   else
01358     *next = crlf + 1;
01359   return WF;
01360 }
01361 
01362 
01363 int
01364 sdp_message_parse (sdp_message_t * sdp, const char *buf)
01365 {
01366 
01367   /* In SDP, headers must be in the right order */
01368   /* This is a simple example
01369      v=0
01370      o=user1 53655765 2353687637 IN IP4 128.3.4.5
01371      s=Mbone Audio
01372      i=Discussion of Mbone Engineering Issues
01373      e=mbone@somewhere.com
01374      c=IN IP4 224.2.0.1/127
01375      t=0 0
01376      m=audio 3456 RTP/AVP 0
01377      a=rtpmap:0 PCMU/8000
01378    */
01379 
01380   char *next_buf;
01381   char *ptr;
01382   int i;
01383 
01384   ptr = (char *) buf;
01385   /* mandatory */
01386 
01387   i = sdp_message_parse_v (sdp, ptr, &next_buf);
01388   if (i == -1)                  /* header is bad */
01389     return -1;
01390   else if (0 == i)              /* header is not "v" */
01391     return -1;
01392   ptr = next_buf;
01393 
01394   /* adtech phone use the wrong ordering and place "s" before "o" */
01395   i = sdp_message_parse_s (sdp, ptr, &next_buf);
01396   if (i == -1)                  /* header is bad */
01397     return -1;
01398   /* else if (0==i) header is not "s" */
01399   /* else ADTECH PHONE DETECTED */
01400 
01401   ptr = next_buf;
01402 
01403   i = sdp_message_parse_o (sdp, ptr, &next_buf);
01404   if (i == -1)                  /* header is bad */
01405     return -1;
01406   else if (0 == i)              /* header is not "o" */
01407     return -1;
01408   ptr = next_buf;
01409 
01410   i = sdp_message_parse_s (sdp, ptr, &next_buf);
01411   if (i == -1)                  /* header is bad */
01412     return -1;
01413   else if (0 == i)              /* header is not "s" */
01414     /* return -1; */
01415     {
01416       OSIP_TRACE (osip_trace
01417                   (__FILE__, __LINE__, OSIP_INFO4, NULL,
01418                    "The \"s\" parameter is mandatory, but this packet does not contain any! - anyway, we don't mind about it.\n"));
01419     }
01420   ptr = next_buf;
01421 
01422   i = sdp_message_parse_i (sdp, ptr, &next_buf);
01423   if (i == -1)                  /* header is bad */
01424     return -1;
01425   ptr = next_buf;
01426 
01427   i = sdp_message_parse_u (sdp, ptr, &next_buf);
01428   if (i == -1)                  /* header is bad */
01429     return -1;
01430   ptr = next_buf;
01431 
01432   i = 1;
01433   while (i == 1)
01434     {
01435       i = sdp_message_parse_e (sdp, ptr, &next_buf);
01436       if (i == -1)              /* header is bad */
01437         return -1;
01438       ptr = next_buf;
01439     }
01440   i = 1;
01441   while (i == 1)
01442     {
01443       i = sdp_message_parse_p (sdp, ptr, &next_buf);
01444       if (i == -1)              /* header is bad */
01445         return -1;
01446       ptr = next_buf;
01447     }
01448 
01449   /* rfc2327: there should be at least of email or phone number! */
01450   if (osip_list_size (sdp->e_emails) == 0 && osip_list_size (sdp->p_phones) == 0)
01451     {
01452       OSIP_TRACE (osip_trace
01453                   (__FILE__, __LINE__, OSIP_INFO4, NULL,
01454                    "The rfc2327 says there should be at least an email or a phone header!- anyway, we don't mind about it.\n"));
01455     }
01456 
01457   i = sdp_message_parse_c (sdp, ptr, &next_buf);
01458 
01459   if (i == -1)                  /* header is bad */
01460     return -1;
01461   ptr = next_buf;
01462 
01463   i = 1;
01464   while (i == 1)
01465     {
01466       i = sdp_message_parse_b (sdp, ptr, &next_buf);
01467       if (i == -1)              /* header is bad */
01468         return -1;
01469       ptr = next_buf;
01470     }
01471 
01472   /* 1 or more "t" header + 0 or more "r" header for each "t" header */
01473   i = sdp_message_parse_t (sdp, ptr, &next_buf);
01474   if (i == -1)                  /* header is bad */
01475     return -1;
01476   else if (i == ERR_DISCARD)
01477     return -1;                  /* t is mandatory */
01478   ptr = next_buf;
01479 
01480   if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01481     return 0;
01482 
01483   i = 1;
01484   while (i == 1)                /* is a "r" header */
01485     {
01486       i = sdp_message_parse_r (sdp, ptr, &next_buf);
01487       if (i == -1)              /* header is bad */
01488         return -1;
01489       ptr = next_buf;
01490       if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01491         return 0;
01492 
01493     }
01494 
01495   {
01496     int more_t_header = 1;
01497 
01498     i = sdp_message_parse_t (sdp, ptr, &next_buf);
01499     if (i == -1)                /* header is bad */
01500       return -1;
01501     ptr = next_buf;
01502 
01503     if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01504       return 0;
01505 
01506     while (more_t_header == 1)
01507       {
01508         i = 1;
01509         while (i == 1)          /* is a "r" header */
01510           {
01511             i = sdp_message_parse_r (sdp, ptr, &next_buf);
01512             if (i == -1)        /* header is bad */
01513               return -1;
01514             ptr = next_buf;
01515             if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01516               return 0;
01517           }
01518 
01519         i = sdp_message_parse_t (sdp, ptr, &next_buf);
01520         if (i == -1)            /* header is bad */
01521           return -1;
01522         else if (i == ERR_DISCARD)
01523           more_t_header = 0;
01524         else
01525           more_t_header = 1;    /* no more "t" headers */
01526         ptr = next_buf;
01527         if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01528           return 0;
01529       }
01530   }
01531 
01532   i = sdp_message_parse_z (sdp, ptr, &next_buf);
01533   if (i == -1)                  /* header is bad */
01534     return -1;
01535   ptr = next_buf;
01536   if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01537     return 0;
01538 
01539   i = sdp_message_parse_k (sdp, ptr, &next_buf);
01540   if (i == -1)                  /* header is bad */
01541     return -1;
01542   ptr = next_buf;
01543   if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01544     return 0;
01545 
01546   /* 0 or more "a" header */
01547   i = 1;
01548   while (i == 1)                /* no more "a" header */
01549     {
01550       i = sdp_message_parse_a (sdp, ptr, &next_buf);
01551           if (i == -1) {
01552                 /* header is bad */
01553         return -1;
01554           }
01555       ptr = next_buf;
01556           if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n')) {
01557                   return 0;
01558           }
01559     }
01560 
01561   /* 0 or more media headers */
01562   {
01563     int more_m_header = 1;
01564 
01565     while (more_m_header == 1)
01566       {
01567 
01568         more_m_header = sdp_message_parse_m (sdp, ptr, &next_buf);
01569                 if (more_m_header == -1) {
01570                   /* header is bad */
01571           return -1;
01572                 }
01573         ptr = next_buf;
01574         if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01575           return 0;
01576 
01577         i = sdp_message_parse_i (sdp, ptr, &next_buf);
01578         if (i == -1)            /* header is bad */
01579           return -1;
01580         ptr = next_buf;
01581         if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01582           return 0;
01583 
01584         i = 1;
01585         while (i == 1)
01586           {
01587             i = sdp_message_parse_c (sdp, ptr, &next_buf);
01588             if (i == -1)        /* header is bad */
01589               return -1;
01590             ptr = next_buf;
01591             if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01592               return 0;
01593           }
01594 
01595         i = 1;
01596         while (i == 1)
01597           {
01598             i = sdp_message_parse_b (sdp, ptr, &next_buf);
01599             if (i == -1)        /* header is bad */
01600               return -1;
01601             ptr = next_buf;
01602             if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01603               return 0;
01604           }
01605         i = sdp_message_parse_k (sdp, ptr, &next_buf);
01606         if (i == -1)            /* header is bad */
01607           return -1;
01608         ptr = next_buf;
01609         if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01610           return 0;
01611         /* 0 or more a headers */
01612         i = 1;
01613         while (i == 1)
01614           {
01615             i = sdp_message_parse_a (sdp, ptr, &next_buf);
01616             if (i == -1)        /* header is bad */
01617               return -1;
01618             ptr = next_buf;
01619             if (*ptr == '\0' || (*ptr == '\r') || (*ptr == '\n'))
01620               return 0;
01621           }
01622       }
01623   }
01624 
01625   return 0;
01626 }
01627 
01628 static int
01629 sdp_append_connection (char *string, int size, char *tmp,
01630                        sdp_connection_t * conn, char **next_tmp)
01631 {
01632   if (conn->c_nettype == NULL)
01633     return -1;
01634   if (conn->c_addrtype == NULL)
01635     return -1;
01636   if (conn->c_addr == NULL)
01637     return -1;
01638 
01639   tmp = __osip_sdp_append_string (string, size, tmp, "c=");
01640   tmp = __osip_sdp_append_string (string, size, tmp, conn->c_nettype);
01641   tmp = __osip_sdp_append_string (string, size, tmp, " ");
01642   tmp = __osip_sdp_append_string (string, size, tmp, conn->c_addrtype);
01643   tmp = __osip_sdp_append_string (string, size, tmp, " ");
01644   tmp = __osip_sdp_append_string (string, size, tmp, conn->c_addr);
01645   if (conn->c_addr_multicast_ttl != NULL)
01646     {
01647       tmp = __osip_sdp_append_string (string, size, tmp, "/");
01648       tmp =
01649         __osip_sdp_append_string (string, size, tmp, conn->c_addr_multicast_ttl);
01650     }
01651   if (conn->c_addr_multicast_int != NULL)
01652     {
01653       tmp = __osip_sdp_append_string (string, size, tmp, "/");
01654       tmp =
01655         __osip_sdp_append_string (string, size, tmp, conn->c_addr_multicast_int);
01656     }
01657   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01658   *next_tmp = tmp;
01659   return 0;
01660 }
01661 
01662 static int
01663 sdp_append_bandwidth (char *string, int size, char *tmp,
01664                       sdp_bandwidth_t * bandwidth, char **next_tmp)
01665 {
01666   if (bandwidth->b_bwtype == NULL)
01667     return -1;
01668   if (bandwidth->b_bandwidth == NULL)
01669     return -1;
01670 
01671   tmp = __osip_sdp_append_string (string, size, tmp, "b=");
01672   tmp = __osip_sdp_append_string (string, size, tmp, bandwidth->b_bwtype);
01673   tmp = __osip_sdp_append_string (string, size, tmp, ":");
01674   tmp = __osip_sdp_append_string (string, size, tmp, bandwidth->b_bandwidth);
01675   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01676 
01677   *next_tmp = tmp;
01678   return 0;
01679 }
01680 
01681 static int
01682 sdp_append_time_descr (char *string, int size, char *tmp,
01683                        sdp_time_descr_t * time_descr, char **next_tmp)
01684 {
01685   int pos;
01686 
01687   if (time_descr->t_start_time == NULL)
01688     return -1;
01689   if (time_descr->t_stop_time == NULL)
01690     return -1;
01691 
01692 
01693   tmp = __osip_sdp_append_string (string, size, tmp, "t=");
01694   tmp = __osip_sdp_append_string (string, size, tmp, time_descr->t_start_time);
01695   tmp = __osip_sdp_append_string (string, size, tmp, " ");
01696   tmp = __osip_sdp_append_string (string, size, tmp, time_descr->t_stop_time);
01697 
01698   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01699 
01700   pos = 0;
01701   while (!osip_list_eol (time_descr->r_repeats, pos))
01702     {
01703       char *str = (char *) osip_list_get (time_descr->r_repeats, pos);
01704 
01705       tmp = __osip_sdp_append_string (string, size, tmp, "r=");
01706       tmp = __osip_sdp_append_string (string, size, tmp, str);
01707       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01708       pos++;
01709     }
01710 
01711   *next_tmp = tmp;
01712   return 0;
01713 }
01714 
01715 static int
01716 sdp_append_key (char *string, int size, char *tmp, sdp_key_t * key,
01717                 char **next_tmp)
01718 {
01719   if (key->k_keytype == NULL)
01720     return -1;
01721 
01722   tmp = __osip_sdp_append_string (string, size, tmp, "k=");
01723   tmp = __osip_sdp_append_string (string, size, tmp, key->k_keytype);
01724   if (key->k_keydata != NULL)
01725     {
01726       tmp = __osip_sdp_append_string (string, size, tmp, ":");
01727       tmp = __osip_sdp_append_string (string, size, tmp, key->k_keydata);
01728     }
01729   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01730   *next_tmp = tmp;
01731   return 0;
01732 }
01733 
01734 static int
01735 sdp_append_attribute (char *string, int size, char *tmp,
01736                       sdp_attribute_t * attribute, char **next_tmp)
01737 {
01738   if (attribute->a_att_field == NULL)
01739     return -1;
01740 
01741   tmp = __osip_sdp_append_string (string, size, tmp, "a=");
01742   tmp = __osip_sdp_append_string (string, size, tmp, attribute->a_att_field);
01743   if (attribute->a_att_value != NULL)
01744     {
01745       tmp = __osip_sdp_append_string (string, size, tmp, ":");
01746       tmp = __osip_sdp_append_string (string, size, tmp, attribute->a_att_value);
01747     }
01748   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01749 
01750   *next_tmp = tmp;
01751   return 0;
01752 }
01753 
01754 /* internal facility */
01755 static int
01756 sdp_append_media (char *string, int size, char *tmp, sdp_media_t * media,
01757                   char **next_tmp)
01758 {
01759   int pos;
01760 
01761   if (media->m_media == NULL)
01762     return -1;
01763   if (media->m_port == NULL)
01764     return -1;
01765   if (media->m_proto == NULL)
01766     return -1;
01767 
01768   tmp = __osip_sdp_append_string (string, size, tmp, "m=");
01769   tmp = __osip_sdp_append_string (string, size, tmp, media->m_media);
01770   tmp = __osip_sdp_append_string (string, size, tmp, " ");
01771   tmp = __osip_sdp_append_string (string, size, tmp, media->m_port);
01772   if (media->m_number_of_port != NULL)
01773     {
01774       tmp = __osip_sdp_append_string (string, size, tmp, "/");
01775       tmp = __osip_sdp_append_string (string, size, tmp, media->m_number_of_port);
01776     }
01777   tmp = __osip_sdp_append_string (string, size, tmp, " ");
01778   tmp = __osip_sdp_append_string (string, size, tmp, media->m_proto);
01779   pos = 0;
01780   while (!osip_list_eol (media->m_payloads, pos))
01781     {
01782       char *str = (char *) osip_list_get (media->m_payloads, pos);
01783 
01784       tmp = __osip_sdp_append_string (string, size, tmp, " ");
01785       tmp = __osip_sdp_append_string (string, size, tmp, str);
01786       pos++;
01787     }
01788   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01789 
01790   if (media->i_info != NULL)
01791     {
01792       tmp = __osip_sdp_append_string (string, size, tmp, "i=");
01793       tmp = __osip_sdp_append_string (string, size, tmp, media->i_info);
01794       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01795     }
01796 
01797   pos = 0;
01798   while (!osip_list_eol (media->c_connections, pos))
01799     {
01800       sdp_connection_t *conn =
01801         (sdp_connection_t *) osip_list_get (media->c_connections, pos);
01802       char *next_tmp2;
01803       int i;
01804 
01805       i = sdp_append_connection (string, size, tmp, conn, &next_tmp2);
01806       if (i != 0)
01807         return -1;
01808       tmp = next_tmp2;
01809       pos++;
01810     }
01811 
01812   pos = 0;
01813   while (!osip_list_eol (media->b_bandwidths, pos))
01814     {
01815       sdp_bandwidth_t *band =
01816         (sdp_bandwidth_t *) osip_list_get (media->b_bandwidths, pos);
01817       char *next_tmp2;
01818       int i;
01819 
01820       i = sdp_append_bandwidth (string, size, tmp, band, &next_tmp2);
01821       if (i != 0)
01822         return -1;
01823       tmp = next_tmp2;
01824       pos++;
01825     }
01826 
01827   if (media->k_key != NULL)
01828     {
01829       char *next_tmp2;
01830       int i;
01831 
01832       i = sdp_append_key (string, size, tmp, media->k_key, &next_tmp2);
01833       if (i != 0)
01834         return -1;
01835       tmp = next_tmp2;
01836     }
01837 
01838   pos = 0;
01839   while (!osip_list_eol (media->a_attributes, pos))
01840     {
01841       sdp_attribute_t *attr =
01842         (sdp_attribute_t *) osip_list_get (media->a_attributes, pos);
01843       char *next_tmp2;
01844       int i;
01845 
01846       i = sdp_append_attribute (string, size, tmp, attr, &next_tmp2);
01847       if (i != 0)
01848         return -1;
01849       tmp = next_tmp2;
01850       pos++;
01851     }
01852 
01853   *next_tmp = tmp;
01854   return 0;
01855 }
01856 
01857 int
01858 sdp_message_to_str (sdp_message_t * sdp, char **dest)
01859 {
01860   int size;
01861   int pos;
01862   char *tmp;
01863   char *string;
01864 
01865   *dest = NULL;
01866   if (!sdp || sdp->v_version == NULL)
01867     return -1;
01868   if (sdp->o_username == NULL ||
01869       sdp->o_sess_id == NULL ||
01870       sdp->o_sess_version == NULL ||
01871       sdp->o_nettype == NULL || sdp->o_addrtype == NULL || sdp->o_addr == NULL)
01872     return -1;
01873 
01874   /* RFC says "s=" is mandatory... rfc2543 (SIP) recommends to
01875      accept SDP datas without s_name... as some buggy implementations
01876      often forget it...
01877    */
01878   /* if (sdp->s_name == NULL)
01879      return -1; */
01880 
01881   size = BODY_MESSAGE_MAX_SIZE;
01882   tmp = (char *) osip_malloc (size);
01883   string = tmp;
01884 
01885   tmp = __osip_sdp_append_string (string, size, tmp, "v=");
01886   tmp = __osip_sdp_append_string (string, size, tmp, sdp->v_version);
01887   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01888   tmp = __osip_sdp_append_string (string, size, tmp, "o=");
01889   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_username);
01890   tmp = __osip_sdp_append_string (string, size, tmp, " ");
01891   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_sess_id);
01892   tmp = __osip_sdp_append_string (string, size, tmp, " ");
01893   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_sess_version);
01894   tmp = __osip_sdp_append_string (string, size, tmp, " ");
01895   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_nettype);
01896   tmp = __osip_sdp_append_string (string, size, tmp, " ");
01897   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_addrtype);
01898   tmp = __osip_sdp_append_string (string, size, tmp, " ");
01899   tmp = __osip_sdp_append_string (string, size, tmp, sdp->o_addr);
01900   tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01901   if (sdp->s_name != NULL)
01902     {
01903       tmp = __osip_sdp_append_string (string, size, tmp, "s=");
01904       tmp = __osip_sdp_append_string (string, size, tmp, sdp->s_name);
01905       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01906     }
01907   if (sdp->i_info != NULL)
01908     {
01909       tmp = __osip_sdp_append_string (string, size, tmp, "i=");
01910       tmp = __osip_sdp_append_string (string, size, tmp, sdp->i_info);
01911       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01912     }
01913   if (sdp->u_uri != NULL)
01914     {
01915       tmp = __osip_sdp_append_string (string, size, tmp, "u=");
01916       tmp = __osip_sdp_append_string (string, size, tmp, sdp->u_uri);
01917       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01918     }
01919   pos = 0;
01920   while (!osip_list_eol (sdp->e_emails, pos))
01921     {
01922       char *email = (char *) osip_list_get (sdp->e_emails, pos);
01923 
01924       tmp = __osip_sdp_append_string (string, size, tmp, "e=");
01925       tmp = __osip_sdp_append_string (string, size, tmp, email);
01926       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01927       pos++;
01928     }
01929   pos = 0;
01930   while (!osip_list_eol (sdp->p_phones, pos))
01931     {
01932       char *phone = (char *) osip_list_get (sdp->p_phones, pos);
01933 
01934       tmp = __osip_sdp_append_string (string, size, tmp, "p=");
01935       tmp = __osip_sdp_append_string (string, size, tmp, phone);
01936       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01937       pos++;
01938     }
01939   if (sdp->c_connection != NULL)
01940     {
01941       char *next_tmp;
01942       int i;
01943 
01944       i = sdp_append_connection (string, size, tmp, sdp->c_connection, &next_tmp);
01945       if (i != 0)
01946         {
01947           osip_free (string);
01948           return -1;
01949         }
01950       tmp = next_tmp;
01951     }
01952   pos = 0;
01953   while (!osip_list_eol (sdp->b_bandwidths, pos))
01954     {
01955       sdp_bandwidth_t *header =
01956         (sdp_bandwidth_t *) osip_list_get (sdp->b_bandwidths, pos);
01957       char *next_tmp;
01958       int i;
01959 
01960       i = sdp_append_bandwidth (string, size, tmp, header, &next_tmp);
01961       if (i != 0)
01962         {
01963           osip_free (string);
01964           return -1;
01965         }
01966       tmp = next_tmp;
01967       pos++;
01968     }
01969 
01970   pos = 0;
01971   while (!osip_list_eol (sdp->t_descrs, pos))
01972     {
01973       sdp_time_descr_t *header =
01974         (sdp_time_descr_t *) osip_list_get (sdp->t_descrs, pos);
01975       char *next_tmp;
01976       int i;
01977 
01978       i = sdp_append_time_descr (string, size, tmp, header, &next_tmp);
01979       if (i != 0)
01980         {
01981           osip_free (string);
01982           return -1;
01983         }
01984       tmp = next_tmp;
01985       pos++;
01986     }
01987 
01988   if (sdp->z_adjustments != NULL)
01989     {
01990       tmp = __osip_sdp_append_string (string, size, tmp, "z=");
01991       tmp = __osip_sdp_append_string (string, size, tmp, sdp->z_adjustments);
01992       tmp = __osip_sdp_append_string (string, size, tmp, CRLF);
01993     }
01994 
01995   if (sdp->k_key != NULL)
01996     {
01997       char *next_tmp;
01998       int i;
01999 
02000       i = sdp_append_key (string, size, tmp, sdp->k_key, &next_tmp);
02001       if (i != 0)
02002         {
02003           osip_free (string);
02004           return -1;
02005         }
02006       tmp = next_tmp;
02007     }
02008 
02009   pos = 0;
02010   while (!osip_list_eol (sdp->a_attributes, pos))
02011     {
02012       sdp_attribute_t *header =
02013         (sdp_attribute_t *) osip_list_get (sdp->a_attributes, pos);
02014       char *next_tmp;
02015       int i;
02016 
02017       i = sdp_append_attribute (string, size, tmp, header, &next_tmp);
02018       if (i != 0)
02019         {
02020           osip_free (string);
02021           return -1;
02022         }
02023       tmp = next_tmp;
02024       pos++;
02025     }
02026 
02027   pos = 0;
02028   while (!osip_list_eol (sdp->m_medias, pos))
02029     {
02030       sdp_media_t *header = (sdp_media_t *) osip_list_get (sdp->m_medias, pos);
02031       char *next_tmp;
02032       int i;
02033 
02034       i = sdp_append_media (string, size, tmp, header, &next_tmp);
02035       if (i != 0)
02036         {
02037           osip_free (string);
02038           return -1;
02039         }
02040       tmp = next_tmp;
02041       pos++;
02042     }
02043   *dest = string;
02044   return 0;
02045 }
02046 
02047 void
02048 sdp_message_free (sdp_message_t * sdp)
02049 {
02050   if (sdp == NULL)
02051     return;
02052   osip_free (sdp->v_version);
02053   osip_free (sdp->o_username);
02054   osip_free (sdp->o_sess_id);
02055   osip_free (sdp->o_sess_version);
02056   osip_free (sdp->o_nettype);
02057   osip_free (sdp->o_addrtype);
02058   osip_free (sdp->o_addr);
02059   osip_free (sdp->s_name);
02060   osip_free (sdp->i_info);
02061   osip_free (sdp->u_uri);
02062 
02063   osip_list_ofchar_free (sdp->e_emails);
02064 
02065   osip_list_ofchar_free (sdp->p_phones);
02066 
02067   sdp_connection_free (sdp->c_connection);
02068 
02069   osip_list_special_free (sdp->b_bandwidths,
02070                           (void *(*)(void *)) &sdp_bandwidth_free);
02071 
02072   osip_list_special_free (sdp->t_descrs, (void *(*)(void *)) &sdp_time_descr_free);
02073 
02074   osip_free (sdp->z_adjustments);
02075   sdp_key_free (sdp->k_key);
02076 
02077   osip_list_special_free (sdp->a_attributes,
02078                           (void *(*)(void *)) &sdp_attribute_free);
02079 
02080   osip_list_special_free (sdp->m_medias, (void *(*)(void *)) &sdp_media_free);
02081 
02082   osip_free (sdp);
02083 }
02084 
02085 int
02086 sdp_message_clone (sdp_message_t * sdp, sdp_message_t ** dest)
02087 {
02088   int i;
02089   char *body;
02090 
02091   i = sdp_message_init (dest);
02092   if (i != 0)
02093     return -1;
02094 
02095   i = sdp_message_to_str (sdp, &body);
02096   if (i != 0)
02097     goto error_sc1;
02098 
02099   i = sdp_message_parse (*dest, body);
02100   osip_free (body);
02101   if (i != 0)
02102     goto error_sc1;
02103 
02104   return 0;
02105 
02106 error_sc1:
02107   sdp_message_free (*dest);
02108   return -1;
02109 }

Generated on Fri Mar 9 19:59:55 2007 for MAD-FCL by  doxygen 1.5.0