Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / libosip2 / src / osipparser2 / osip_rfc3264.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 <stdlib.h>
21
22 #include <osipparser2/osip_port.h>
23 #include <osipparser2/osip_rfc3264.h>
24 #include <osip_rfc3264i.h> /* internal include */
25
26 /**
27  * Initialize negotiation facility..
28  * @param config The element to work on.
29  */
30 int osip_rfc3264_init (struct osip_rfc3264 **config)
31 {
32   osip_rfc3264_t *cnf;
33   *config = NULL;
34   cnf = (osip_rfc3264_t *) osip_malloc (sizeof(osip_rfc3264_t));
35   if (cnf==NULL)
36     return -1;
37   memset(cnf, 0, sizeof(osip_rfc3264_t));
38   *config = cnf;
39   return 0;
40 }
41
42
43 /**
44  * Free negotiation facility.
45  * @param config The element to work on.
46  */
47 void osip_rfc3264_free (struct osip_rfc3264 *config)
48 {
49   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
50   int i;
51   if (config==NULL) return;
52
53   for (i=0;i<MAX_AUDIO_CODECS; i++)
54     {
55       if (cnf->audio_medias[i]!=NULL)
56         {
57           sdp_media_free(cnf->audio_medias[i]);
58           cnf->audio_medias[i] = NULL;
59         }
60     }
61   for (i=0;i<MAX_VIDEO_CODECS; i++)
62     {
63       if (cnf->video_medias[i]!=NULL)
64         {
65           sdp_media_free(cnf->video_medias[i]);
66           cnf->video_medias[i] = NULL;
67         }
68     }
69   for (i=0;i<MAX_T38_CODECS; i++)
70     {
71       if (cnf->t38_medias[i]!=NULL)
72         {
73           sdp_media_free(cnf->t38_medias[i]);
74           cnf->t38_medias[i] = NULL;
75         }
76     }
77   for (i=0;i<MAX_APP_CODECS; i++)
78     {
79       if (cnf->app_medias[i]!=NULL)
80         {
81           sdp_media_free(cnf->app_medias[i]);
82           cnf->app_medias[i] = NULL;
83         }
84     }
85   osip_free(cnf);
86 }
87
88
89 /**
90  * Test if a media exist in the configuration.
91  * @param config The element to work on.
92  * @param pos The index of the media element.
93  */
94 int osip_rfc3264_endof_media (struct osip_rfc3264 *config, int pos)
95 {
96   if (config==NULL) return -1;
97
98   return 0;
99 }
100
101
102 /**
103  * Get a media from the configuration.
104  * @param config The element to work on.
105  * @param pos The index of the media element to get.
106  */
107 sdp_media_t *osip_rfc3264_get (struct osip_rfc3264 *config, int pos)
108 {
109   if (config==NULL) return NULL;
110
111   return NULL;
112 }
113
114
115 /**
116  * Remove a media from the configuration.
117  * @param config The element to work on.
118  * @param pos The index of the media element to remove.
119  */
120 int osip_rfc3264_remove (struct osip_rfc3264 *config, int pos)
121 {
122   if (config==NULL) return -1;
123
124   return 0;
125 }
126
127
128 /**
129  * Remove all medias from the configuration.
130  * @param config The element to work on.
131  */
132 int osip_rfc3264_reset_media (struct osip_rfc3264 *config)
133 {
134   if (config==NULL) return -1;
135
136   return 0;
137 }
138
139
140 /**
141  * Add a media (for audio) in the configuration.
142  * @param config The element to work on.
143  * @param pos The index of the media element to add.
144  */
145 int osip_rfc3264_add_audio_media (struct osip_rfc3264 *config, sdp_media_t *med, int pos)
146 {
147   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
148   if (config==NULL) return -1;
149   if (pos>=MAX_AUDIO_CODECS) return -1;
150
151   if (pos==-1)
152     {
153       for (pos=0;pos<MAX_AUDIO_CODECS && cnf->audio_medias[pos]!=NULL; pos++)
154         { }
155     }
156   if (pos>=MAX_AUDIO_CODECS) return -1; /* no space left */
157
158   cnf->audio_medias[pos] = med;
159   return 0;
160 }
161
162
163 /**
164  * Remove a media in the configuration.
165  * @param config The element to work on.
166  * @param pos The index of the media element to remove.
167  */
168 int osip_rfc3264_del_audio_media (struct osip_rfc3264 *config, int pos)
169 {
170   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
171   if (config==NULL) return -1;
172   if (pos>=MAX_AUDIO_CODECS) return -1;
173   sdp_media_free(cnf->audio_medias[pos]);
174   cnf->audio_medias[pos] = NULL;
175   return 0;
176 }
177
178 /**
179  * Add a media (for video) in the configuration.
180  * @param config The element to work on.
181  * @param pos The index of the media element to add.
182  */
183 int osip_rfc3264_add_video_media (struct osip_rfc3264 *config, sdp_media_t *med, int pos)
184 {
185   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
186   if (config==NULL) return -1;
187   if (pos>=MAX_VIDEO_CODECS) return -1;
188
189   if (pos==-1)
190     {
191       for (pos=0;pos<MAX_VIDEO_CODECS && cnf->video_medias[pos]!=NULL; pos++)
192         { }
193     }
194   if (pos>=MAX_VIDEO_CODECS) return -1; /* no space left */
195
196   cnf->video_medias[pos] = med;
197   return 0;
198 }
199
200
201 /**
202  * Remove a media in the configuration.
203  * @param config The element to work on.
204  * @param pos The index of the media element to remove.
205  */
206 int osip_rfc3264_del_video_media (struct osip_rfc3264 *config, int pos)
207 {
208   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
209   if (config==NULL) return -1;
210   if (pos>=MAX_VIDEO_CODECS) return -1;
211   sdp_media_free(cnf->video_medias[pos]);
212   cnf->video_medias[pos] = NULL;
213   return 0;
214 }
215
216 /**
217  * Add a media (for t38) in the configuration.
218  * @param config The element to work on.
219  * @param pos The index of the media element to add.
220  */
221 int osip_rfc3264_add_t38_media (struct osip_rfc3264 *config, sdp_media_t *med, int pos)
222 {
223   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
224   if (config==NULL) return -1;
225   if (pos>=MAX_T38_CODECS) return -1;
226
227   if (pos==-1)
228     {
229       for (pos=0;pos<MAX_T38_CODECS && cnf->t38_medias[pos]!=NULL; pos++)
230         { }
231     }
232   if (pos>=MAX_T38_CODECS) return -1; /* no space left */
233
234   cnf->t38_medias[pos] = med;
235   return 0;
236 }
237
238
239 /**
240  * Remove a media in the configuration.
241  * @param config The element to work on.
242  * @param pos The index of the media element to remove.
243  */
244 int osip_rfc3264_del_t38_media (struct osip_rfc3264 *config, int pos)
245 {
246   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
247   if (config==NULL) return -1;
248   if (pos>=MAX_T38_CODECS) return -1;
249   sdp_media_free(cnf->t38_medias[pos]);
250   cnf->t38_medias[pos] = NULL;
251   return 0;
252 }
253
254 /**
255  * Search for support of a special codec.
256  * @param config The element to work on.
257  */
258   sdp_media_t *osip_rfc3264_find_audio (struct osip_rfc3264 *config, char *payload,
259                                         char *rtpmap)
260 {
261   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
262   int i;
263   if (config==NULL) return NULL;
264
265   if (rtpmap==NULL)
266     {
267       for (i=0;i<MAX_AUDIO_CODECS; i++)
268         {
269           if (cnf->audio_medias[i]!=NULL)
270             {
271               sdp_media_t *med = cnf->audio_medias[i];
272               char *str = (char *) osip_list_get (med->m_payloads, 0);
273               /* static payload?: only compare payload number */
274               if (strlen(str)==strlen(payload)
275                   && 0==osip_strcasecmp(str, payload))
276                 return med;
277             }
278         }
279       return NULL;
280     }
281
282   for (i=0;i<MAX_AUDIO_CODECS; i++)
283     {
284       if (cnf->audio_medias[i]!=NULL)
285         {
286           sdp_media_t *med = cnf->audio_medias[i];
287
288           int pos = 0;
289           while (!osip_list_eol (med->a_attributes, pos))
290             {
291               sdp_attribute_t *attr =
292                 (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
293
294               if (0==osip_strcasecmp("rtpmap", attr->a_att_field)
295                   &&  attr->a_att_value!=NULL)
296                 {
297                   char *tmp = strchr(attr->a_att_value, ' ');
298                   char *tmp2 = strchr(rtpmap, ' ');
299                   if (tmp!=NULL && tmp2!=NULL)
300                     {
301                       if (0==osip_strcasecmp(tmp,tmp2))
302                         return med;
303                     }
304                 }
305               pos++;
306             }
307         }
308     }
309
310   return NULL;
311 }
312
313 /**
314  * Search for support of a special codec.
315  * @param config The element to work on.
316  */
317   sdp_media_t *osip_rfc3264_find_video (struct osip_rfc3264 *config, char *payload,
318                                         char *rtpmap)
319 {
320   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
321   int i;
322   if (config==NULL) return NULL;
323
324   if (rtpmap==NULL)
325     {
326       for (i=0;i<MAX_VIDEO_CODECS; i++)
327         {
328           if (cnf->video_medias[i]!=NULL)
329             {
330               sdp_media_t *med = cnf->video_medias[i];
331               char *str = (char *) osip_list_get (med->m_payloads, 0);
332               /* static payload?: only compare payload number */
333               if (strlen(str)==strlen(payload)
334                   && 0==osip_strcasecmp(str, payload))
335                 return med;
336             }
337         }
338       return NULL;
339     }
340
341   for (i=0;i<MAX_VIDEO_CODECS; i++)
342     {
343       if (cnf->video_medias[i]!=NULL)
344         {
345           sdp_media_t *med = cnf->video_medias[i];
346
347           int pos = 0;
348           while (!osip_list_eol (med->a_attributes, pos))
349             {
350               sdp_attribute_t *attr =
351                 (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
352
353               if (0==osip_strcasecmp("rtpmap", attr->a_att_field)
354                   &&  attr->a_att_value!=NULL)
355                 {
356                   char *tmp = strchr(attr->a_att_value, ' ');
357                   char *tmp2 = strchr(rtpmap, ' ');
358                   if (tmp!=NULL && tmp2!=NULL)
359                     {
360                       if (0==osip_strcasecmp(tmp,tmp2))
361                         return med;
362                     }
363                 }
364               pos++;
365             }
366         }
367     }
368
369   return NULL;
370 }
371
372 /**
373  * Search for support of a special codec.
374  * @param config The element to work on.
375  */
376   sdp_media_t *osip_rfc3264_find_t38 (struct osip_rfc3264 *config, char *payload)
377 {
378   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
379   if (config==NULL) return NULL;
380   return NULL;
381 }
382
383 /**
384  * Search for support of a special codec.
385  * @param config The element to work on.
386  */
387   sdp_media_t *osip_rfc3264_find_app (struct osip_rfc3264 *config, char *payload)
388 {
389   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
390   if (config==NULL) return NULL;
391   return NULL;
392 }
393
394 /**
395  * Compare remote sdp packet against local supported media.
396  *    Only one media line is checked.
397  *
398  * @param config The element to work on.
399  * @param remote_sdp The remote SDP packet.
400  * @param audio_tab The local list of media supported by both side.
401  * @param video_tab The local list of media supported by both side.
402  * @param t38_tab The local list of media supported by both side.
403  * @param app_tab The local list of media supported by both side.
404  * @param pos_media The position of the media line to match.
405  */
406 int osip_rfc3264_match(struct osip_rfc3264 *config,
407                        sdp_message_t *remote_sdp,
408                        sdp_media_t *audio_tab[],
409                        sdp_media_t *video_tab[],
410                        sdp_media_t *t38_tab[],
411                        sdp_media_t *app_tab[],
412                        int pos_media)
413 {
414   sdp_media_t *remote_med;
415   int pos;
416
417   audio_tab[0] = NULL;
418   video_tab[0] = NULL;
419   t38_tab[0] = NULL;
420   app_tab[0] = NULL;
421
422   if (config==NULL) return -1;
423
424   pos=0;
425   while (!sdp_message_endof_media (remote_sdp, pos))
426     {
427       if (pos_media==0)
428         {
429           remote_med = osip_list_get (remote_sdp->m_medias, pos);
430           if (remote_med->m_media!=NULL
431               && 0 == osip_strcasecmp (remote_med->m_media, "audio"))
432             {
433               osip_rfc3264_match_audio(config, remote_sdp, remote_med, audio_tab);
434             }
435           else if (remote_med->m_media!=NULL
436                    && 0 == osip_strcasecmp (remote_med->m_media, "video"))
437             {
438               osip_rfc3264_match_video(config, remote_sdp, remote_med, video_tab);
439             }
440           else if (remote_med->m_media!=NULL
441                    && 0 == osip_strcasecmp (remote_med->m_media, "image"))
442             {
443               osip_rfc3264_match_t38(config, remote_sdp, remote_med, t38_tab);
444             }
445           else if (remote_med->m_media!=NULL
446                    && 0 == osip_strcasecmp (remote_med->m_media, "application"))
447             {
448               osip_rfc3264_match_app(config, remote_sdp, remote_med, app_tab);
449             }
450           return 0;
451         }
452
453       remote_med=NULL;
454       pos++;
455       pos_media--;
456     }
457
458   return -1;
459 }
460
461 /**
462  * Compare remote sdp packet against local supported media for audio.
463  * @param config The element to work on.
464  * @param remote_sdp The remote SDP packet.
465  * @param remote_med The remote Media SDP line.
466  * @param audio_tab The local list of media supported by both side.
467  */
468 int osip_rfc3264_match_audio(struct osip_rfc3264 *config,
469                              sdp_message_t *remote_sdp,
470                              sdp_media_t *remote_med,
471                              sdp_media_t *audio_tab[])
472 {
473   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
474   int num=0;
475   int pos;
476   audio_tab[0] = NULL;
477
478   if (cnf==NULL) return -1;
479
480   /* search for the audio media line */
481   pos=0;
482   while (!osip_list_eol (remote_med->m_payloads, pos))
483     {
484       char *payload = (char *) osip_list_get (remote_med->m_payloads, pos);
485       sdp_media_t *local_med;
486       char *rtpmap = NULL;
487       int posattr = 0;
488
489       /* search for the rtpmap associated to the payload */
490       while (!osip_list_eol (remote_med->a_attributes, posattr))
491         {
492           sdp_attribute_t *attr =
493             (sdp_attribute_t *) osip_list_get (remote_med->a_attributes, posattr);
494           if (0==osip_strncasecmp(attr->a_att_field, "rtpmap", 6))
495             {
496               if (attr->a_att_value!=NULL &&
497                   0==osip_strncasecmp(attr->a_att_value, payload, strlen(payload)))
498                 {
499                   /* TODO check if it was not like 101: == 10 */
500                   rtpmap = attr->a_att_value;
501                   break;
502                 }
503             }
504           posattr++;
505         }
506
507       local_med = osip_rfc3264_find_audio(config, payload, rtpmap);
508       if (local_med!=NULL)
509         {
510           /* found a supported codec? */
511           audio_tab[num] = local_med;
512           num++;
513         }
514
515       /* search for support of this codec in local media list */
516       pos++;
517     }
518
519   audio_tab[num] = NULL;
520   return 0;
521 }
522
523 /**
524  * Compare remote sdp packet against local supported media for video.
525  * @param config The element to work on.
526  * @param remote_sdp The remote SDP packet.
527  * @param remote_med The remote Media SDP line.
528  * @param video_tab The local list of media supported by both side.
529  */
530 int osip_rfc3264_match_video(struct osip_rfc3264 *config,
531                              sdp_message_t *remote_sdp,
532                              sdp_media_t *remote_med,
533                              sdp_media_t *video_tab[])
534 {
535   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
536   int num=0;
537   int pos;
538   video_tab[0] = NULL;
539
540   if (cnf==NULL) return -1;
541
542   /* search for the video media line */
543
544   pos=0;
545   while (!osip_list_eol (remote_med->m_payloads, pos))
546     {
547       char *payload = (char *) osip_list_get (remote_med->m_payloads, pos);
548       sdp_media_t *local_med;
549       char *rtpmap = NULL;
550       int posattr = 0;
551
552       /* search for the rtpmap associated to the payload */
553       while (!osip_list_eol (remote_med->a_attributes, posattr))
554         {
555           sdp_attribute_t *attr =
556             (sdp_attribute_t *) osip_list_get (remote_med->a_attributes, posattr);
557           if (0==osip_strncasecmp(attr->a_att_field, "rtpmap", 6))
558             {
559               if (attr->a_att_value!=NULL &&
560                   0==osip_strncasecmp(attr->a_att_value, payload, strlen(payload)))
561                 {
562                   /* TODO check if it was not like 101: == 10 */
563                   rtpmap = attr->a_att_value;
564                   break;
565                 }
566             }
567           posattr++;
568         }
569
570       local_med = osip_rfc3264_find_video(config, payload, rtpmap);
571       if (local_med!=NULL)
572         {
573           /* found a supported codec? */
574           video_tab[num] = local_med;
575           num++;
576         }
577
578       /* search for support of this codec in local media list */
579       pos++;
580     }
581
582   video_tab[num] = NULL;
583   return 0;
584 }
585
586 /**
587  * Compare remote sdp packet against local supported media for t38.
588  * @param config The element to work on.
589  * @param remote_sdp The remote SDP packet.
590  * @param remote_med The remote Media SDP line.
591  * @param t38_tab The local list of media supported by both side.
592  */
593 int osip_rfc3264_match_t38(struct osip_rfc3264 *config,
594                            sdp_message_t *remote_sdp,
595                            sdp_media_t *remote_med,
596                            sdp_media_t *t38_tab[])
597 {
598   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
599
600   t38_tab[0] = NULL;
601
602   if (cnf==NULL) return -1;
603
604   return 0;
605 }
606
607 /**
608  * Compare remote sdp packet against local supported media for application.
609  * @param config The element to work on.
610  * @param remote_sdp The remote SDP packet.
611  * @param remote_med The remote Media SDP line.
612  * @param app_tab The local list of media supported by both side.
613  */
614 int osip_rfc3264_match_app(struct osip_rfc3264 *config,
615                            sdp_message_t *remote_sdp,
616                            sdp_media_t *remote_med,
617                            sdp_media_t *app_tab[])
618 {
619   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
620
621   app_tab[0] = NULL;
622
623   if (cnf==NULL) return -1;
624
625   return 0;
626 }
627
628
629 /**
630  * Prepare an uncomplete answer.
631  * @param config The element to work on.
632  * @param remote_sdp The remote SDP packet.
633  * @param local_sdp The local SDP packet to prepare.
634  * @param length The local SDP packet's length.
635  */
636 int osip_rfc3264_prepare_answer(struct osip_rfc3264 *config,
637                                 sdp_message_t *remote_sdp,
638                                 char *local_sdp, int length)
639 {
640   int pos, pos2;
641   if (config==NULL) return -1;
642   if (remote_sdp==NULL) return -1;
643
644   if (osip_list_size(remote_sdp->t_descrs)>0)
645
646 #if (defined WIN32 || defined _WIN32_WCE)   
647   _snprintf(local_sdp, 4096,
648            "v=0\r\n\
649 o=userX 20000001 20000001 IN IP4 TOREPLACE\r\n\
650 s=-\r\n\
651 c=IN IP4 TOREPLACE\r\n");
652 #else
653   snprintf(local_sdp, 4096,
654            "v=0\r\n\
655 o=userX 20000001 20000001 IN IP4 TOREPLACE\r\n\
656 s=-\r\n\
657 c=IN IP4 TOREPLACE\r\n");
658 #endif
659   /* Fill t= (and r=) fields */
660   pos=0;
661   while (!osip_list_eol(remote_sdp->t_descrs, pos))
662     {
663       char tmp[100];
664       sdp_time_descr_t *td;
665       td = (sdp_time_descr_t *) osip_list_get(remote_sdp->t_descrs, pos);
666       if (td->t_start_time!=NULL && td->t_stop_time!=NULL)
667 #if (defined WIN32 || defined _WIN32_WCE)   
668           _snprintf(tmp, 100, "t=%s %s\r\n", td->t_start_time, td->t_stop_time);
669 #else
670       snprintf(tmp, 100, "t=%s %s\r\n", td->t_start_time, td->t_stop_time);
671 #endif
672       else
673 #if (defined WIN32 || defined _WIN32_WCE)        
674         _snprintf(tmp, 100, "t=0 0\r\n");
675 #else
676         snprintf(tmp, 100, "t=0 0\r\n");
677 #endif
678       if ((int)(strlen(local_sdp)+strlen(tmp)+1)<length)
679
680         {
681           strcat(local_sdp, tmp);
682
683           pos2 = 0;
684           while (!osip_list_eol (td->r_repeats, pos2))
685             {
686               char *str = (char *) osip_list_get (td->r_repeats, pos2);
687
688               if ((int)(strlen(local_sdp)+strlen(str)+5+1)<length)
689               {
690                 strcat(local_sdp, "r=");
691                 strcat(local_sdp, str);
692                 strcat(local_sdp, "\r\n");
693               }
694               else
695                 return -1;
696               pos2++;
697             }
698         }
699       else
700         return -1;
701       pos++;
702     }
703
704
705   pos=0;
706   while (!osip_list_eol(remote_sdp->m_medias, pos))
707     {
708       int posattr = 0;
709       char tmp[200];
710       char tmp2[200];
711       char inactive='X';
712       sdp_media_t *med;
713
714 #if (defined WIN32 || defined _WIN32_WCE)   
715       _snprintf(tmp2, 199, "\r\n");
716 #else
717       snprintf(tmp2, 199, "\r\n");
718 #endif
719       med = (sdp_media_t *) osip_list_get(remote_sdp->m_medias, pos);
720
721       /* search for the rtpmap associated to the payload */
722       while (!osip_list_eol (med->a_attributes, posattr))
723         {
724           sdp_attribute_t *attr =
725             (sdp_attribute_t *) osip_list_get (med->a_attributes, posattr);
726           if (strlen(attr->a_att_field)==8 && attr->a_att_value==NULL)
727             {
728               if (0==osip_strncasecmp(attr->a_att_field, "sendonly", 8))
729                 {
730 #if (defined WIN32 || defined _WIN32_WCE)   
731                   _snprintf(tmp2, 199, "\r\na=recvonly\r\n");
732 #else
733                   snprintf(tmp2, 199, "\r\na=recvonly\r\n");
734 #endif
735                   break;
736                 }
737               else if (0==osip_strncasecmp(attr->a_att_field, "recvonly", 8))
738                 {
739 #if (defined WIN32 || defined _WIN32_WCE) 
740                   _snprintf(tmp2, 199, "\r\na=sendonly\r\n");
741 #else
742                   snprintf(tmp2, 199, "\r\na=sendonly\r\n");
743 #endif
744                   break;
745                 }
746               else if (0==osip_strncasecmp(attr->a_att_field, "sendrecv", 8))
747                 {
748                   break;
749                 }
750               else if (0==osip_strncasecmp(attr->a_att_field, "inactive", 8))
751                 {
752 #if (defined WIN32 || defined _WIN32_WCE) 
753                   _snprintf(tmp2, 199, "\r\na=inactive\r\n");
754 #else
755                   snprintf(tmp2, 199, "\r\na=inactive\r\n");
756 #endif
757                   inactive='0';
758                   break;
759                 }
760             }
761           posattr++;
762         }
763
764       if (med->m_media!=NULL && med->m_proto!=NULL && med->m_number_of_port==NULL)
765         {
766 #if (defined WIN32 || defined _WIN32_WCE) 
767         _snprintf(tmp, 199, "m=%s %c %s ", med->m_media, inactive, med->m_proto);
768 #else
769         snprintf(tmp, 199, "m=%s %c %s ", med->m_media, inactive, med->m_proto);
770 #endif
771         }
772       else if (med->m_media!=NULL && med->m_proto!=NULL && med->m_number_of_port==NULL)
773         {
774 #if (defined WIN32 || defined _WIN32_WCE) 
775           _snprintf(tmp, 199, "m=%s %c %s/%s ", med->m_media, inactive, med->m_proto, med->m_number_of_port);
776 #else
777           snprintf(tmp, 199, "m=%s %c %s/%s ", med->m_media, inactive, med->m_proto, med->m_number_of_port);
778 #endif
779         }
780       else
781         return -1;
782
783       if ((int)(strlen(local_sdp)+strlen(tmp)+1)<length)
784         strcat(local_sdp, tmp);
785       else return -1;
786
787       if ((int)(strlen(local_sdp)+strlen(tmp2)+1)<length)
788         strcat(local_sdp, tmp2);
789       else return -1;
790
791       pos++;
792     }
793
794   return 0;
795 }
796
797 /**
798  * Agree to support a specific codec.
799  *   This method should be called for each codec returned by
800  *   osip_rfc3264_match(...) that the calle agree to support.
801  *
802  * @param config The element to work on.
803  * @param remote_sdp The remote SDP packet.
804  * @param local_sdp The local SDP packet to complete.
805  * @param med One of the media returned by osip_rfc3264_match.
806  * @param mline The position of the media line to complete.
807  */
808 int
809 osip_rfc3264_complete_answer(struct osip_rfc3264 *config,
810                              sdp_message_t *remote_sdp,
811                              sdp_message_t *local_sdp,
812                              sdp_media_t *med,
813                              int mline)
814 {
815   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
816   sdp_media_t *remote_med = NULL;
817   sdp_media_t *local_med = NULL;
818   int pos;
819   if (cnf==NULL) return -1;
820   if (remote_sdp==NULL) return -1;
821   if (med==NULL) return -1;
822   if (mline<0) return -1;
823   if (local_sdp==NULL) return -1;
824   pos=0;
825   while (!osip_list_eol(remote_sdp->m_medias, pos))
826     {
827       remote_med = (sdp_media_t *) osip_list_get(remote_sdp->m_medias, pos);
828       local_med = (sdp_media_t *) osip_list_get(local_sdp->m_medias, pos);
829       if (pos==mline) break;
830       remote_med = NULL;
831       local_med = NULL;
832       pos++;
833     }
834   if (remote_med==NULL) return -1;
835
836   pos = 0;
837   while (!osip_list_eol (med->a_attributes, pos))
838     {
839       sdp_attribute_t *attr =
840         (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
841
842       if (0==osip_strcasecmp("rtpmap", attr->a_att_field)
843           &&  attr->a_att_value!=NULL)
844         {
845           sdp_attribute_t *mattr;
846           char *tmp;
847
848           /* fill the m= line */
849           tmp = (char*) osip_list_get(med->m_payloads, 0);
850           if (tmp!=NULL)
851             osip_list_add(local_med->m_payloads, osip_strdup(tmp), -1);
852           else
853             return -1;
854
855           sdp_attribute_init(&mattr);
856           mattr->a_att_field = osip_strdup(attr->a_att_field);
857           mattr->a_att_value = osip_strdup(attr->a_att_value);
858
859           /* fill the a= line */
860           osip_list_add (local_med->a_attributes, mattr, -1);
861           return 0;
862         }
863     }
864
865   return -1; /* no rtpmap found? It is mandatory in audio and video media */
866 }
867
868 /**
869  * Agree to support a specific codec.
870  *   This method should be called for each codec returned by
871  *   osip_rfc3264_match(...)
872  *
873  * @param config The element to work on.
874  * @param med One of the media returned by osip_rfc3264_match
875  * @param remote_sdp The remote SDP packet.
876  * @param local_sdp The local SDP packet to prepare.
877  */
878 int osip_rfc3264_accept_codec(struct osip_rfc3264 *config,
879                               sdp_media_t *med,
880                               sdp_message_t *remote_sdp,
881                               sdp_message_t *local_sdp)
882 {
883   if (config==NULL) return -1;
884
885   return 0;
886 }
887
888
889 /* #ifdef RFC3264_DEBUG */
890
891 /**
892  * List supported codecs. (for debugging purpose only)
893  *
894  * @param config The element to work on.
895  */
896 int __osip_rfc3264_print_codecs(struct osip_rfc3264 *config)
897 {
898   osip_rfc3264_t *cnf = (osip_rfc3264_t*) config;
899   int i,pos;
900   if (config==NULL) return -1;
901
902   fprintf(stdout, "Audio codecs Supported:\n");
903   for (i=0;i<MAX_AUDIO_CODECS; i++)
904     {
905       if (cnf->audio_medias[i]!=NULL)
906         {
907           sdp_media_t *med = cnf->audio_medias[i];
908           char *str = (char *) osip_list_get (med->m_payloads, 0);
909           fprintf(stdout, "\tm=%s %s %s %s\n",
910                   med->m_media,
911                   med->m_port,
912                   med->m_proto,
913                   str);
914           pos = 0;
915           while (!osip_list_eol (med->a_attributes, pos))
916             {
917               sdp_attribute_t *attr =
918                 (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
919               fprintf(stdout, "\ta=%s:%s\n",
920                       attr->a_att_field,
921                       attr->a_att_value);
922               pos++;
923             }
924           fprintf(stdout, "\n");
925         }
926     }
927
928   fprintf(stdout, "Video codecs Supported:\n");
929   for (i=0;i<MAX_VIDEO_CODECS; i++)
930     {
931       if (cnf->video_medias[i]!=NULL)
932         {
933           sdp_media_t *med = cnf->video_medias[i];
934           char *str = (char *) osip_list_get (med->m_payloads, 0);
935           fprintf(stdout, "\tm=%s %s %s %s\n",
936                   med->m_media,
937                   med->m_port,
938                   med->m_proto,
939                   str);
940           pos = 0;
941           while (!osip_list_eol (med->a_attributes, pos))
942             {
943               sdp_attribute_t *attr =
944                 (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
945               fprintf(stdout, "\ta=%s:%s\n",
946                       attr->a_att_field,
947                       attr->a_att_value);
948               pos++;
949             }
950           fprintf(stdout, "\n");
951         }
952     }
953
954   fprintf(stdout, "t38 configs Supported:\n");
955   for (i=0;i<MAX_T38_CODECS; i++)
956     {
957       if (cnf->t38_medias[i]!=NULL)
958         {
959           sdp_media_t *med = cnf->t38_medias[i];
960           fprintf(stdout, "m=%s %s %s X\n",
961                   med->m_media,
962                   med->m_port,
963                   med->m_proto);
964           pos = 0;
965           while (!osip_list_eol (med->a_attributes, pos))
966             {
967               sdp_attribute_t *attr =
968                 (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
969               fprintf(stdout, "\ta=%s:%s\n",
970                       attr->a_att_field,
971                       attr->a_att_value);
972               pos++;
973             }
974           fprintf(stdout, "\n");
975         }
976     }
977
978   fprintf(stdout, "Application config Supported:\n");
979   for (i=0;i<MAX_APP_CODECS; i++)
980     {
981       if (cnf->app_medias[i]!=NULL)
982         {
983           sdp_media_t *med = cnf->app_medias[i];
984           fprintf(stdout, "m=%s %s %s X\n",
985                   med->m_media,
986                   med->m_port,
987                   med->m_proto);
988           pos = 0;
989           while (!osip_list_eol (med->a_attributes, pos))
990             {
991               sdp_attribute_t *attr =
992                 (sdp_attribute_t *) osip_list_get (med->a_attributes, pos);
993               fprintf(stdout, "\ta=%s:%s\n",
994                       attr->a_att_field,
995                       attr->a_att_value);
996               pos++;
997             }
998           fprintf(stdout, "\n");
999         }
1000     }
1001
1002   return 0;
1003 }
1004
1005 /* #endif */