source: trunk/ETSI-Testsuites/ETSI_auto_IOT/codec/c++/sdp_codets.cpp @ 53

Last change on this file since 53 was 22, checked in by rings, 14 years ago
  • Property svn:executable set to *
File size: 37.2 KB
Line 
1#include <cstdlib>
2
3
4#ifdef WIN32
5#include <winsock2.h>
6#else
7#include <arpa/inet.h> // used for validting ipv6 addresses (should be replaced w/ boost/asio.hpp for better portability)
8#endif
9
10
11// workaround to compile with cygwin
12// (AF_INET6 is not included by arpa/inet.h and we could not find the
13//  correct header to include without having conflicting definitions)
14#ifdef __CYGWIN__
15#define AF_INET6  23
16#endif
17
18#include "gen_classes.h"
19#include "Regex.h"
20
21namespace t3devlib { namespace gen {
22
23
24// Definition of character classes used to be used in the regular expressions
25// (within [])
26#define SDPCHARS_VCHAR "\\x21-\\x7e"
27#define SDPCHARS_EMAIL_SAFE "\\x01-\\x09\\x0b\\x0c\\x0e-\\x27\\x2a-\\x3b\\x3d\\x3f-\\xff"
28#define SDPCHARS_ATEXT "a-zA-Z0-9!#$%&'*+-/=?^_`{|}~"
29#define SDPCHARS_BYTE_STRING "\\x01-\\x09\\x0b\\x0c\\x0e-\\xff"
30
31
32// Definition of common regular expression reused many times within the
33// decoder
34//
35// Note: these definitions shall not contain any group match '(' ')' to avoid
36// side effect (the index of the subsequent group match would be shifted)
37// -> all parenthesis group needed should be implemented with '(?:' ')' so
38//    that they are not indexed
39#define SDPREG_SP " "
40#define SDPREG_NON_WS_STRING "[" SDPCHARS_VCHAR "\\x80-\\xff]+"
41#define SDPREG_TOKEN "[\\x21\\x23-\\x27\\x2a\\x2b\\x2d\\x2e\\x30-\\x39\\x41-\\x5a\\x5e-\\x7e]+"
42#define SDPREG_DECIMAL_UCHAR "(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(?![0-9])"
43#define SDPREG_IP4_ADDRESS SDPREG_DECIMAL_UCHAR "(?:[.]" SDPREG_DECIMAL_UCHAR"){3}"
44#define SDPREG_INTEGER "[1-9][0-9]*"
45#define SDPREG_TIME_INTEGER "[0-9][0-9]*"
46#define SDPREG_BYTE_STRING "["SDPCHARS_BYTE_STRING"]+"
47
48// TODO: support the folding whitespaces/obsolete addresses/... ?
49#define SDPREG_ADDR_SPEC "[" SDPCHARS_ATEXT "][." SDPCHARS_ATEXT "]*@[" SDPCHARS_ATEXT "][." SDPCHARS_ATEXT "]*"
50
51// This regex differs from the BNF to avoid matching a space or dash at the
52// end of the number
53#define SDPREG_PHONE "[+]?[0-9](?:[- 0-9]*[0-9])?"
54
55
56inline bool logical_xor (bool a, bool b)
57{
58        return (a && !b) || (!a && b);
59}
60
61
62
63//
64// Implementation of the decoder for SDP
65//
66
67
68void SDP_Message::PreDecode (Buffer& buffer) throw (DecodeError)
69{
70        Get_protocol_version().SetFormat(Integer::AsciiDecimal);
71}
72
73
74void pre_decode_optional_field_multiple_times (RecordOfSetOf& value, int id, Buffer& buffer, const char* field_letter, void (*hyp_size_func)(int), void (*hyp_field_length_func)(int) )
75{
76        static Regex reg_field ("((?:\r\n)?)(([a-z])=)([^\\r\\n\\x00]*)");
77        if (!reg_field.Match (buffer))
78                goto finished;
79
80        if (logical_xor (id, reg_field.GetMatchedLength (1)))
81                // the first line MUST NOT be preceeded by CRLF
82                // the next lines MUST be preceeded by CRLF
83                //  -> otherwise we assume this is the last field
84                goto finished;
85
86        if (reg_field.GetMatchedString (3) != field_letter) {
87                assert (id > 0);// the field letter is already checked in
88                                // SDP_Message::PreDecodeField
89                                // the assertion is useful to ensure
90                                // that we cannot have an empty
91                                // record of (in that case the field
92                                // must be omitted in SDP_Message)
93                goto finished;
94        }
95
96        (*hyp_field_length_func) (reg_field.GetMatchedLength(4));
97        reg_field.MovePast (buffer, 2);
98        return;
99
100finished:
101        // did not match -> last field
102        (*hyp_size_func) (-2);
103}
104
105
106void SDP_Message::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
107{
108        static Regex reg_field("^(([a-z])=)([^\\r\\n\\x00]*)");
109
110        const char* expected = NULL;
111
112        switch (id)
113        {
114        case id_protocol_version:       expected = "v";         goto mandatory;
115        case id_origin:                 expected = "o";         goto mandatory;
116        case id_session_name:           expected = "s";         goto mandatory;
117        case id_information:            expected = "i";         goto optional_once;
118
119        // TODO: check that this is a valid URI ???
120        case id_uri:                    expected = "u";         goto optional_once;
121        case id_emails:                 expected = "e";         goto optional_many;
122        case id_phone_numbers:          expected = "p";         goto optional_many;
123        case id_connection:             expected = "c";         goto optional_once;
124        case id_bandwidth:              expected = "b";         goto optional_many;
125        case id_times:                  return; // times is not optional => always present
126        // FIXME: SDP_timezone_list should not be here -> the TTCN-3 types should be changed
127        // in the BNF, "z=" is allowed once after each "t=" fields (not after
128        // the last one only)
129        case id_timezone_adjustments:   expected = "z";         goto optional_once;
130        case id_key:                    expected = "k";         goto optional_once;
131        case id_attributes:             expected = "a";         goto optional_many;
132        case id_media_list:             expected = "m";         goto optional_many;
133        }
134
135        return;
136mandatory:
137        reg_field.AssertMatch (buffer, this);
138
139        SetHypFieldLength (id, reg_field.GetMatchedLength(3));
140
141        if (reg_field.GetMatchedString(2) != expected) {
142                DecodeError e(this);
143                e.Msg() << "missing mandatory field " << expected << "= before field " << reg_field.GetMatchedString(1) << endl;
144                throw e;
145        }
146        reg_field.MovePast (buffer, 1);
147        return;
148
149optional_once:
150        if (reg_field.Match (buffer) &&
151            reg_field.GetMatchedString(2) == expected)
152        {
153                // the field is present
154                SetHypFieldIsPresent (id, 1);
155                SetHypFieldLength (id, reg_field.GetMatchedLength(3));
156                reg_field.MovePast (buffer, 1);
157        } else {
158                // the field is not present
159                SetHypFieldIsPresent (id, 0);
160        }
161        return;
162
163optional_many:
164        SetHypFieldIsPresent (id,
165                (reg_field.Match (buffer) &&
166                 reg_field.GetMatchedString(2) == expected)
167                ? 1
168                : 0);
169}
170
171void SDP_Message::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
172{
173        // Here we match the trailing CRLF in the case the field is present
174        static Regex reg_crlf ("^\r\n");
175
176
177        if (!IsPresent (id))
178                return;
179
180        // the time field is not declared as optional
181        // therefore we must check that the list is not empty
182        if ((id == id_times) && (Get_times().GetSize() == 0))
183                return;
184
185        reg_crlf.AssertMatch (buffer, this);
186        reg_crlf.MovePast (buffer);
187}
188
189void SDP_Origin::PreDecode (Buffer& buffer) throw (DecodeError)
190{
191        static Regex reg_origin ("("SDPREG_NON_WS_STRING")"     // username
192                        SDPREG_SP "([0-9]+)"            // session-id
193                        SDPREG_SP "([0-9]+)"            // session-version
194                        SDPREG_SP "("SDPREG_TOKEN")"    // net-type
195                        SDPREG_SP "("SDPREG_TOKEN")"    // addr-type
196                        SDPREG_SP "("SDPREG_NON_WS_STRING")"); // unicast-address
197        reg_origin.AssertMatch (buffer, this);
198        for (int i=0 ; i<6 ; i++) {
199                SetHypFieldLength (i, reg_origin.GetMatchedLength(i+1));
200        }
201}
202
203void SDP_Origin::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
204{
205        if (id) {
206                static Regex reg_sp (" ");
207                reg_sp.AssertMatch (buffer, this);
208                reg_sp.MovePast (buffer);
209        }
210}
211
212#define SDP_CODET_HEADER_LIST(letter, type) \
213        void type::PreDecodeField (int id, Buffer& buffer) throw (DecodeError) \
214        { \
215                pre_decode_optional_field_multiple_times (*this, id, buffer, letter, &SetHypSize, &SetHypFieldLength); \
216        }
217
218SDP_CODET_HEADER_LIST ("e", SDP_email_list);
219SDP_CODET_HEADER_LIST ("p", SDP_phone_list);
220SDP_CODET_HEADER_LIST ("b", SDP_bandwidth_list);
221SDP_CODET_HEADER_LIST ("r", SDP_repeat_list);
222SDP_CODET_HEADER_LIST ("a", SDP_attribute_list);
223SDP_CODET_HEADER_LIST ("c", SDP_connection_list);
224
225
226
227void dummy (int a) {
228}
229// SDL_time and SDP_media_desc list are a little unusual compared to other
230// headers since these record can contain a list of headers
231//
232// In order to be able to decode it, we will not put any length
233// constraint on this header (thus passing &dummy instead of
234// &SetHypFieldLength), then it will be possible to decode the
235// repeate headers after the CRLF
236void SDP_time_list::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
237{
238        pre_decode_optional_field_multiple_times (*this, id, buffer, "t", &SetHypSize, &dummy);
239}
240void SDP_media_desc_list::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
241{
242        pre_decode_optional_field_multiple_times (*this, id, buffer, "m", &SetHypSize, &dummy);
243}
244
245
246void SDP_contact::PreDecode (Buffer& buffer) throw (DecodeError)
247{
248        static Regex reg_addrspec_comment ("^(" SDPREG_ADDR_SPEC ")(" SDPREG_SP "[(](["SDPCHARS_EMAIL_SAFE"]+)[)])?");
249        static Regex reg_dispname_and_addr ("^(["SDPCHARS_EMAIL_SAFE"]+)" SDPREG_SP "<(" SDPREG_ADDR_SPEC ")>");
250       
251        static Regex reg_phone_comment ("^(" SDPREG_PHONE ")(" SDPREG_SP "[(](["SDPCHARS_EMAIL_SAFE"]+)[)])?");
252        static Regex reg_dispname_and_phone ("^(["SDPCHARS_EMAIL_SAFE"]+)" SDPREG_SP "<(" SDPREG_PHONE ")>");
253
254        Regex *reg_normal, *reg_reverse;
255        if (dynamic_cast<SDP_phone_list*>(GetParent())) {
256                // this is a phone contact
257                reg_normal  = &reg_phone_comment;
258                reg_reverse = &reg_dispname_and_phone;
259        } else {
260                // this is an email contact
261                reg_normal  = &reg_addrspec_comment;
262                reg_reverse = &reg_dispname_and_addr;
263        }
264
265        // by default we assume that there is no name displayed
266        SetHypFieldIsPresent (id_disp_name, 0);
267
268        if (reg_normal->Match (buffer)) {
269                mReverseOrder = false;
270                SetHypFieldLength (id_addr_or_phone, reg_normal->GetMatchedLength (1));
271                mHasComment = reg_normal->GetMatchedLength (2);
272                if (mHasComment) {
273                        SetHypFieldIsPresent (id_disp_name, 1);
274                        SetHypFieldLength (id_disp_name, reg_normal->GetMatchedLength (3));
275                }
276        } else if (reg_reverse->Match (buffer)) {
277                mReverseOrder = true;
278                SetHypFieldLength (id_addr_or_phone, reg_reverse->GetMatchedLength (2));
279                SetHypFieldIsPresent (id_disp_name, 1);
280                SetHypFieldLength (id_disp_name, reg_reverse->GetMatchedLength (1));
281                // remember the position of the display name to be able
282                // to decode it later
283                mNextPosition = buffer.GetPosition();
284                // then place the cursor of the buffer at the position of the
285                // email address
286                reg_reverse->MoveAt (buffer, 2);
287        } else {
288                throw DecodeError (this, "Cannot match email address or phone number\n");
289        }
290}
291
292void SDP_contact::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
293{
294        if (mReverseOrder) {
295                if (id == id_addr_or_phone) {
296                        int disp_name_position = mNextPosition;
297                        // remember the position past the closing ">"
298                        mNextPosition = buffer.GetPosition() + 8;
299                        buffer.SetPosition (disp_name_position);
300                } else {
301                        // once everything is decoded we move forward to the
302                        // end of the message field
303                        buffer.SetPosition (mNextPosition);
304                }
305        } else if (mHasComment) {
306                buffer.SetPosition (buffer.GetPosition() + (
307                        (id == id_addr_or_phone)
308                                ? 16    // move past the " ("
309                                : 8     // move past the ")"
310                ));
311        }
312}
313
314void SDP_connection::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
315{
316        if (id == id_net_type) {
317                static Regex reg_connection ("^(" SDPREG_TOKEN ") (" SDPREG_TOKEN ") (" SDPREG_NON_WS_STRING ")");
318
319                reg_connection.AssertMatch (buffer, this);
320                SetHypFieldLength (id_net_type, reg_connection.GetMatchedLength (1));
321                SetHypFieldLength (id_addr_type, reg_connection.GetMatchedLength (2));
322                SetHypFieldLength (id_conn_addr, reg_connection.GetMatchedLength (3));
323               
324        } else {
325                buffer.SetPosition (buffer.GetPosition() + 8); // move past the SP
326        }
327}
328
329void SDP_conn_addr::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
330{
331        if (id == id_addr) {
332                static Regex reg_ip4 ("^("SDPREG_IP4_ADDRESS")((?:[/]("SDPREG_INTEGER"))?((?:[/]("SDPREG_INTEGER"))?))");
333                static Regex reg_ip6 ("^([0-9a-fA-F.:]+)((?:[/]("SDPREG_INTEGER"))?)");
334                unsigned char ip6_addr[16];
335       
336                // use ascii format for the integers
337                Get_ttl().SetFormat(Integer::AsciiDecimal);
338                Get_num_of_addr().SetFormat(Integer::AsciiDecimal);
339       
340                // ttl and addr_num are not present by default
341                SetHypFieldIsPresent (id_ttl, 0);
342                SetHypFieldIsPresent (id_num_of_addr, 0);
343/*
344reg_ip4.AssertMatch (buffer, this);
345for (int i=0 ; i<6 ; i++) {
346        cerr << "Matched string " << i << " -> " << reg_ip4.GetMatchedString (i) << endl;
347        cerr << "Matched length " << i << " -> " << reg_ip4.GetMatchedLength (i) << endl;
348}
349*/
350                if (reg_ip4.Match (buffer)) {
351                        SetHypFieldLength (id_addr, reg_ip4.GetMatchedLength (1));
352                        if (atoi (reg_ip4.GetMatchedString(1).c_str()) < 224) {
353                                // unicast address
354                                if (reg_ip4.GetMatchedLength(2) | reg_ip4.GetMatchedLength(4))
355                                        throw DecodeError (this, "TTL and/or number of connections fields can be present only with multicast addresses\n");
356
357                        } else {
358                                // multicast address
359                                if (! reg_ip4.GetMatchedLength (2))
360                                        throw DecodeError (this, "IPv4 multicast address must be followed with the TTL");
361                                SetHypFieldIsPresent (id_ttl, 1);
362                                SetHypFieldLength (id_ttl, reg_ip4.GetMatchedLength (3));
363                                if (reg_ip4.GetMatchedLength (4)) {
364                                        SetHypFieldIsPresent (id_num_of_addr, 1);
365                                        SetHypFieldLength (id_num_of_addr, reg_ip4.GetMatchedLength (5));
366                                }
367                        }
368                } else if (     reg_ip6.Match (buffer)
369#ifndef WIN32
370                                // FIXME: inet_pton does not exist in WIN32
371                        && (inet_pton (AF_INET6, reg_ip6.GetMatchedString(1).c_str(), &ip6_addr) == 1) // if it does not contain a valid ipv6 address, then
372                                // we will parse it as another address family
373#endif
374                        ) {
375                        SetHypFieldLength (id_addr, reg_ip6.GetMatchedLength (1));
376                        if (ip6_addr[0] != 0xFF) {
377                                // unicast address
378                                if (reg_ip4.GetMatchedLength(2))
379                                        throw DecodeError (this, "The number of connections can be present only with multicast addresses\n");
380
381                        } else {
382                                // multicast address
383                                if (reg_ip6.GetMatchedLength (2)) {
384                                        SetHypFieldIsPresent (id_num_of_addr, 1);
385                                        SetHypFieldLength (id_num_of_addr, reg_ip6.GetMatchedLength (3));
386                                }
387                        }
388                } else {
389                        // if it is not an ipv4 or ipv6 address
390                        // then we put everything in the addr field
391                }
392               
393        } else if (GetHypFieldIsPresent (id)) {
394                buffer.SetPosition (buffer.GetPosition() + 8); // move past the "/"
395        }
396}
397
398void SDP_bandwidth::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
399{
400        if (id == id_modifier) {
401                static Regex reg_bw ("^(" SDPREG_TOKEN "):([0-9]+)");
402                reg_bw.AssertMatch (buffer, this);
403                SetHypFieldLength (id_modifier, reg_bw.GetMatchedLength(1));
404                SetHypFieldLength (id_bandwidth, reg_bw.GetMatchedLength(2));
405        } else {
406                Get_bandwidth().SetFormat(Integer::AsciiDecimal);
407                Unsigned(8).Decode(buffer); // move past the colon
408        }
409}
410
411void SDP_time::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
412{
413        if (id == id_time_repeat) {
414                static Regex reg_repeat ("^(\r\n)r=");
415
416                if (reg_repeat.Match (buffer)) {
417                        SetHypFieldIsPresent (id, 1);
418                        reg_repeat.MovePast (buffer, 1);
419                } else {
420                        SetHypFieldIsPresent (id, 0);
421                }
422        }
423}
424
425void SDP_time_field::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
426{
427        if (id == id_start_time) {
428                static Regex reg_times ("^(" SDPREG_TIME_INTEGER ")" SDPREG_SP "(" SDPREG_TIME_INTEGER ")");
429                reg_times.AssertMatch (buffer, this);
430                SetHypFieldLength (id_start_time, reg_times.GetMatchedLength (1));
431                SetHypFieldLength (id_stop_time, reg_times.GetMatchedLength (2));
432        } else {
433                Unsigned(8).Decode (buffer); // move past the SP
434        }
435}
436
437void SDP_typed_time::PreDecode (Buffer& buffer) throw (DecodeError)
438{
439        static Regex reg_ttime ("^(-?[0-9]*)([dhms]?)");
440        reg_ttime.AssertMatch (buffer, this);
441
442        Get_time().SetFormat(Integer::AsciiDecimal);
443        SetHypFieldLength (id_time, reg_ttime.GetMatchedLength (1));
444
445        bool has_unit = reg_ttime.GetMatchedLength (2);
446        SetHypFieldIsPresent (id_unit, has_unit ? 1 : 0);
447        if (has_unit) {
448                SetHypFieldLength (id_unit, 8);
449        }
450}
451
452void SDP_repeat::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
453{
454        if (id == id_active) {
455                static Regex reg_sp ("^" SDPREG_SP);
456                reg_sp.AssertMatch (buffer, this);
457                reg_sp.MovePast (buffer, 0);
458        }
459}
460
461void SDP_typed_time_list::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
462{
463        static Regex reg_sp ("^(" SDPREG_SP ")[0-9]+");
464        if (reg_sp.Match (buffer)) {
465                reg_sp.MovePast (buffer, 1);
466        } else {
467                SetHypSize (-2);
468        }
469}
470
471void SDP_timezone_list::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
472{
473        static Regex reg_sp ("^(" SDPREG_SP ")[0-9]");
474        if (reg_sp.Match (buffer)) {
475                reg_sp.MovePast (buffer, 1);
476        } else {
477                SetHypSize (-2);
478        }
479}
480
481void SDP_timezone::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
482{
483        if (id == id_adjustment_time) {
484                static Regex reg_tz ("^([1-9][0-9]*)" SDPREG_SP);
485                reg_tz.AssertMatch (buffer, this);
486                SetHypFieldLength (id_adjustment_time, reg_tz.GetMatchedLength(1));
487        } else {
488                Unsigned(8).Decode(buffer); // move past the SP
489        }
490}
491
492void SDP_key::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
493{
494        if (id == id_method) {
495                static Regex reg_method ("^(prompt|clear|base64|uri)(:?)");
496                reg_method.AssertMatch (buffer, this);
497
498                if (reg_method.GetMatchedString(1) == "prompt") {
499                        if (reg_method.GetMatchedLength(2))
500                                throw DecodeError (this, "the 'prompt' method must not be followed by a value\n");
501                } else {
502                        if (!reg_method.GetMatchedLength(2))
503                                throw DecodeError (this, "the method must not be followed by a value\n");
504                }
505                SetHypFieldLength (id_method, reg_method.GetMatchedLength (1));
506                SetHypFieldIsPresent (id_key, reg_method.GetMatchedLength (2) ? 1 : 0);
507        } else {
508                if (GetHypFieldIsPresent (id)) {
509                        Unsigned(8).Decode(buffer); // move past the colon
510                        // TODO: validate the content of the key ?
511                }
512        }
513}
514
515class SdpAttributeMap {
516public:
517        struct Entry {
518                Entry (const char* name, int id_attr)
519                 : mName (name), mIdAttribute (id_attr)
520                 {}
521                const std::string       mName;
522                const int               mIdAttribute;
523        };
524
525        static const Entry& GetByName (const std::string& key)
526        {
527                const mMapName_t& m = msInstance.mMapName;
528                mMapName_t::const_iterator it = m.find (key);
529                if (it != m.end()) {
530                        return *it->second;
531                } else {
532                        return *msInstance.mUndef;
533                }
534        }
535       
536        static const Entry& GetByIdMessageHeader (int key)
537        {
538                const std::map<int, Entry*>& m = msInstance.mMapIdAttribute;
539                std::map <int, Entry*>::const_iterator it = m.find (key);
540                if (it != m.end()) {
541                        return *it->second;
542                } else {
543                        return *msInstance.mUndef;
544                }
545        }
546
547
548private:
549        void AddEntry (const Entry& entry) {
550                mEntries.push_back(entry);
551                Entry& e = *mEntries.rbegin();
552               
553                //TODO: check unicity
554                mMapName[e.mName] = &e;
555                mMapIdAttribute[e.mIdAttribute] = &e;
556        }
557
558        SdpAttributeMap() {
559
560#define SDP_ATTRIBUTE_ADD(name) AddEntry (Entry (#name, SDP_attribute::id_ ## name));
561
562                //              Name
563                SDP_ATTRIBUTE_ADD (cat);
564                SDP_ATTRIBUTE_ADD (keywds);
565                SDP_ATTRIBUTE_ADD (tool);
566                SDP_ATTRIBUTE_ADD (ptime);
567                SDP_ATTRIBUTE_ADD (recvonly);
568                SDP_ATTRIBUTE_ADD (sendrecv);
569                SDP_ATTRIBUTE_ADD (sendonly);
570                SDP_ATTRIBUTE_ADD (inactive);
571                SDP_ATTRIBUTE_ADD (orient);
572                AddEntry (Entry ("type", SDP_attribute::id_sdp_type));
573                SDP_ATTRIBUTE_ADD (sdp_type);
574                SDP_ATTRIBUTE_ADD (charset);
575                SDP_ATTRIBUTE_ADD (sdplang);
576                SDP_ATTRIBUTE_ADD (lang);
577                SDP_ATTRIBUTE_ADD (framerate);
578                SDP_ATTRIBUTE_ADD (quality);
579                SDP_ATTRIBUTE_ADD (fmtp);
580                SDP_ATTRIBUTE_ADD (rtpmap);
581                SDP_ATTRIBUTE_ADD (rtcp);
582
583                // RFC 3312 attributes
584                SDP_ATTRIBUTE_ADD (curr);
585                SDP_ATTRIBUTE_ADD (des);
586                SDP_ATTRIBUTE_ADD (conf);
587                {
588                        mEntries.push_back(Entry("", SDP_attribute::id_unknown));
589                        Entry& e = *mEntries.rbegin();
590                        mMapIdAttribute[e.mIdAttribute] = &e;
591                        mUndef = &e;
592                }
593        }
594
595        static SdpAttributeMap          msInstance;
596
597        std::list<Entry>                mEntries;
598        Entry*                          mUndef;
599
600        typedef std::map <std::string, Entry*>  mMapName_t;
601        mMapName_t                      mMapName;
602        std::map <int, Entry*>          mMapIdAttribute;
603};
604SdpAttributeMap SdpAttributeMap::msInstance;
605
606void SDP_attribute::PreDecode (Buffer& buffer) throw (DecodeError)
607{
608        Regex reg_attr ("^("SDPREG_TOKEN")(?:(:)("SDPREG_BYTE_STRING"))?");
609        reg_attr.AssertMatch (buffer, this);
610
611        int id = SdpAttributeMap::GetByName (reg_attr.GetMatchedString(1)).mIdAttribute;
612       
613        SetHypChosenId (id);
614        if (id != id_unknown) {
615                SetHypLength (reg_attr.GetMatchedLength(3));
616                reg_attr.MovePast(buffer,
617                        (reg_attr.GetMatchedLength(2) ? 2 : 1)
618                );
619        }
620}
621
622void SDP_attribute_unknown::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
623{
624        if (id == id_name) {
625                Regex reg_attr ("^("SDPREG_TOKEN")((?::("SDPREG_BYTE_STRING"))?)");
626                reg_attr.AssertMatch (buffer, this);
627
628                SetHypFieldLength (id_name, reg_attr.GetMatchedLength (1));
629
630                int val_len = reg_attr.GetMatchedLength(3);
631                SetHypFieldIsPresent (id_attr_value, (val_len ? 1 : 0));
632                if (val_len)
633                        SetHypFieldLength (id_attr_value, val_len);
634        } else if (GetHypFieldIsPresent (id)){
635                Unsigned(8).Decode(buffer); // move past the colon
636        }
637}
638
639void SDP_attribute_curr::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
640{
641        if (id == 0) {
642                Regex reg_attr ("^("SDPREG_TOKEN")" SDPREG_SP "(e2e|local|remote)" SDPREG_SP "(none|sendrecv|send|recv)");
643                reg_attr.AssertMatch (buffer, this);
644
645                SetHypFieldLength (0, reg_attr.GetMatchedLength (1));
646                SetHypFieldLength (1, reg_attr.GetMatchedLength (2));
647                SetHypFieldLength (2, reg_attr.GetMatchedLength (3));
648
649        } else if (GetHypFieldIsPresent (id)){
650                Unsigned(8).Decode(buffer); // move past the space
651        }
652}
653
654void SDP_attribute_des::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
655{
656        if (id == 0) {
657                Regex reg_attr ("^("SDPREG_TOKEN")" SDPREG_SP "(mandatory|optional|none|failure|unknown)" SDPREG_SP "(e2e|local|remote)" SDPREG_SP "(none|sendrecv|send|recv)");
658                reg_attr.AssertMatch (buffer, this);
659
660                SetHypFieldLength (0, reg_attr.GetMatchedLength (1));
661                SetHypFieldLength (1, reg_attr.GetMatchedLength (2));
662                SetHypFieldLength (2, reg_attr.GetMatchedLength (3));
663                SetHypFieldLength (3, reg_attr.GetMatchedLength (4));
664
665        } else if (GetHypFieldIsPresent (id)){
666                Unsigned(8).Decode(buffer); // move past the space
667        }
668}
669
670void SDP_attribute_conf::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
671{
672        if (id == 0) {
673                Regex reg_attr ("^("SDPREG_TOKEN")" SDPREG_SP "(e2e|local|remote)" SDPREG_SP "(none|sendrecv|send|recv)");
674                reg_attr.AssertMatch (buffer, this);
675
676                SetHypFieldLength (0, reg_attr.GetMatchedLength (1));
677                SetHypFieldLength (1, reg_attr.GetMatchedLength (2));
678                SetHypFieldLength (2, reg_attr.GetMatchedLength (3));
679
680        } else if (GetHypFieldIsPresent (id)){
681                Unsigned(8).Decode(buffer); // move past the space
682        }
683}
684
685void SDP_media_field::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
686{
687        static Regex reg_media ("^("SDPREG_TOKEN")" SDPREG_SP "([0-9/]+)" SDPREG_SP "("SDPREG_TOKEN"(?:/"SDPREG_TOKEN")*)" );
688
689        if (id==0) {
690                reg_media.AssertMatch (buffer, this);
691                SetHypFieldLength (id_media, reg_media.GetMatchedLength (1));
692                SetHypFieldLength (id_ports, reg_media.GetMatchedLength (2));
693                SetHypFieldLength (id_transport, reg_media.GetMatchedLength (3));
694        } else if (id != id_fmts) {
695                Unsigned(8).Decode(buffer); // move past the SP
696        }
697}
698
699void SDP_media_field::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
700{
701        static Regex reg_space ("^"SDPREG_SP);
702        if(id == id_ports) {
703                // Necessary as 2nd part of SDP_media_port regex
704                // could be a mismatch (ex: num-of_ports=0) !
705                reg_space.AssertMatch(buffer, this);
706        }
707}
708
709void SDP_media_port::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
710{
711        static Regex reg_port ("^([0-9]+)(/("SDPREG_INTEGER"))?");
712
713        if (id == 0) {
714                reg_port.AssertMatch (buffer, this);
715               
716                Get_port_number().SetFormat(Integer::AsciiDecimal);
717                SetHypFieldLength (id_port_number, reg_port.GetMatchedLength(1));
718                if (reg_port.GetMatchedLength (2)) {
719                        SetHypFieldIsPresent (id_num_of_ports, 1);
720                        SetHypFieldLength (id_num_of_ports, reg_port.GetMatchedLength(3));
721                        Get_num_of_ports().SetFormat(Integer::AsciiDecimal);
722                } else {
723                        SetHypFieldIsPresent (id_num_of_ports, 0);
724                }
725        } else {
726                if (GetHypFieldIsPresent (id)) {
727                        Unsigned(8).Decode(buffer); // move past the '/'
728                }
729        }
730}
731
732void SDP_fmt_list::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
733{
734        static Regex reg_fmt ("^"SDPREG_SP"("SDPREG_TOKEN")");
735        if (reg_fmt.Match (buffer)) {
736                reg_fmt.MoveAt (buffer, 1);
737                SetHypFieldLength (reg_fmt.GetMatchedLength(1));
738        } else {
739                SetHypSize (-2);
740        }
741}
742
743void SDP_media_desc::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
744{
745        if (id == id_media_field)
746                // media_field is always present and the "m=" was
747                // already processed by SDP_message::PreDecodeField()
748                return;
749
750        static Regex reg_field("^(([a-z])=)([^\\r\\n\\x00]*)");
751
752        const char* expected = NULL;
753
754        switch (id)
755        {
756        case id_information:            expected = "i";         goto optional_once;
757        case id_connections:            expected = "c";         goto optional_many;
758        case id_bandwidth:              expected = "b";         goto optional_once;
759        case id_key:                    expected = "k";         goto optional_once;
760        case id_attributes:             expected = "a";         goto optional_many;
761        }
762
763        return;
764mandatory:
765        reg_field.AssertMatch (buffer, this);
766
767        SetHypFieldLength (id, reg_field.GetMatchedLength(3));
768
769        if (reg_field.GetMatchedString(2) != expected) {
770                DecodeError e(this);
771                e.Msg() << "missing mandatory field " << expected << "= before field " << reg_field.GetMatchedString(1) << endl;
772                throw e;
773        }
774        reg_field.MovePast (buffer, 1);
775        return;
776
777optional_once:
778        if (reg_field.Match (buffer) &&
779            reg_field.GetMatchedString(2) == expected)
780        {
781                // the field is present
782                SetHypFieldIsPresent (id, 1);
783                SetHypFieldLength (id, reg_field.GetMatchedLength(3));
784                reg_field.MovePast (buffer, 1);
785        } else {
786                // the field is not present
787                SetHypFieldIsPresent (id, 0);
788        }
789        return;
790
791optional_many:
792        SetHypFieldIsPresent (id,
793                (reg_field.Match (buffer) &&
794                 reg_field.GetMatchedString(2) == expected)
795                ? 1
796                : 0);
797}
798
799void SDP_media_desc::PostDecodeField (int id, Buffer& buffer) throw (DecodeError)
800{
801        static Regex reg_crlf ("^\r\n");
802        if (IsPresent (id)) {
803                reg_crlf.AssertMatch (buffer, this);
804                reg_crlf.MovePast (buffer);
805        }
806}
807
808void SDP_media_desc::PostDecode (Buffer& buffer) throw (DecodeError)
809{
810        buffer.SetPosition(buffer.GetPosition()-16); // go back 2 chars so that the CRLF is matched by the SDP_Message::PostDecodeField();
811}
812
813
814//
815// Implementation of the encoder for SDP
816//
817
818void SDP_Message::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
819{
820        Charstring csHeader;
821
822        if(IsPresent(field_id)) {
823                switch(field_id) {
824                case id_protocol_version:
825                        Get_protocol_version().SetFormat(Integer::AsciiDecimal);
826                        csHeader.SetValue("v=");
827                        csHeader.Encode(buffer);
828                        break;         
829                case id_origin:
830                        csHeader.SetValue("o=");
831                        csHeader.Encode(buffer);
832                        break;         
833                case id_session_name:
834                        csHeader.SetValue("s=");
835                        csHeader.Encode(buffer);
836                        break;         
837                case id_information:
838                        csHeader.SetValue("i=");
839                        csHeader.Encode(buffer);
840                        break;         
841                case id_uri:
842                        csHeader.SetValue("u=");
843                        csHeader.Encode(buffer);
844                        break;         
845                case id_connection:
846                        csHeader.SetValue("c=");
847                        csHeader.Encode(buffer);
848                        break;         
849                case id_key:
850                        csHeader.SetValue("k=");
851                        csHeader.Encode(buffer);
852                        break;         
853                case id_timezone_adjustments:
854                        csHeader.SetValue("z=");
855                        csHeader.Encode(buffer);
856                        break;         
857                }
858        }
859}
860
861void SDP_Message::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
862{
863        Charstring csCRLF;
864        csCRLF.SetValue("\r\n");
865
866
867        switch(field_id) {
868        case id_protocol_version:
869        case id_origin:
870        case id_session_name:
871        case id_information:
872        case id_uri:
873        case id_connection:
874        case id_key:
875        case id_timezone_adjustments:
876                if(IsPresent(field_id)) {
877                        csCRLF.Encode(buffer);
878                }
879                break;
880        case id_emails:
881        case id_phone_numbers:
882        case id_bandwidth:
883        case id_times:
884        case id_attributes:
885        case id_media_list:
886                break;
887        }
888}
889
890void SDP_Origin::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
891{
892        Charstring csSpace;
893        csSpace.SetValue(" ");
894
895        if(field_id != 0) {
896                csSpace.Encode(buffer);
897        }
898}
899
900void SDP_connection::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
901{
902        Charstring csSpace;
903        csSpace.SetValue(" ");
904
905        if(field_id != 0) {
906                csSpace.Encode(buffer);
907        }
908}
909
910void SDP_conn_addr::PreEncode (Buffer& buffer) throw (EncodeError)
911{
912        Get_ttl().SetFormat(Integer::AsciiDecimal);
913        Get_num_of_addr().SetFormat(Integer::AsciiDecimal);
914}
915
916void SDP_conn_addr::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
917{
918        Charstring csSlash;
919        csSlash.SetValue("/");
920
921        if(IsPresent(field_id)) {
922                switch(field_id) {
923                case id_ttl:
924                case id_num_of_addr:
925                        csSlash.Encode(buffer);
926                        break;
927                }
928        }
929}
930
931void SDP_email_list::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
932{
933        Charstring csHeader;
934
935        csHeader.SetValue("e=");
936        csHeader.Encode(buffer);
937}
938
939void SDP_email_list::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
940{
941        Charstring csCRLF;
942        csCRLF.SetValue("\r\n");
943
944        csCRLF.Encode(buffer);
945}
946
947void SDP_phone_list::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
948{
949        Charstring csHeader;
950
951        csHeader.SetValue("p=");
952        csHeader.Encode(buffer);
953}
954
955void SDP_phone_list::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
956{
957        Charstring csCRLF;
958        csCRLF.SetValue("\r\n");
959
960        csCRLF.Encode(buffer);
961}
962
963void SDP_bandwidth_list::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
964{
965}
966
967void SDP_bandwidth::PostEncode (Buffer& buffer) throw (EncodeError)
968{
969        Charstring csCRLF;
970        csCRLF.SetValue("\r\n");
971
972        csCRLF.Encode(buffer);
973}
974
975void SDP_bandwidth::PreEncode (Buffer& buffer) throw (EncodeError)
976{
977        Charstring csHeader;
978
979        csHeader.SetValue("b=");
980        csHeader.Encode(buffer);
981
982        Get_bandwidth().SetFormat(Integer::AsciiDecimal);
983}
984
985void SDP_bandwidth::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
986{
987        Charstring csColon;
988        csColon.SetValue(":");
989
990        if(field_id == id_modifier) {
991                csColon.Encode(buffer);
992        }
993}
994
995void SDP_timezone::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
996{
997        Charstring csSpace;
998        csSpace.SetValue(" ");
999
1000        if(field_id != 0) {
1001                csSpace.Encode(buffer);
1002        }
1003}
1004
1005void SDP_timezone_list::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1006{
1007        Charstring csSpace;
1008        csSpace.SetValue(" ");
1009
1010        if(field_id != 0) {
1011                csSpace.Encode(buffer);
1012        }
1013}
1014
1015void SDP_typed_time::PreEncode (Buffer& buffer) throw (EncodeError)
1016{
1017        Get_time().SetFormat(Integer::AsciiDecimal);
1018}
1019
1020void SDP_attribute_list::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1021{
1022        Charstring csHeader;
1023
1024        csHeader.SetValue("a=");
1025        csHeader.Encode(buffer);
1026}
1027
1028void SDP_attribute_list::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1029{
1030        Charstring csCRLF;
1031        csCRLF.SetValue("\r\n");
1032
1033        csCRLF.Encode(buffer);
1034}
1035
1036void SDP_media_field::PreEncode (Buffer& buffer) throw (EncodeError)
1037{
1038        Charstring csHeader;
1039
1040        csHeader.SetValue("m=");
1041        csHeader.Encode(buffer);
1042}
1043
1044void SDP_media_field::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1045{
1046        Charstring csSpace;
1047        csSpace.SetValue(" ");
1048
1049        if(field_id != 0) {
1050                csSpace.Encode(buffer);
1051        }
1052}
1053
1054void SDP_fmt_list::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1055{
1056        Charstring csSpace;
1057        csSpace.SetValue(" ");
1058
1059        if(field_id != 0) {
1060                csSpace.Encode(buffer);
1061        }
1062}
1063
1064void SDP_media_port::PreEncode (Buffer& buffer) throw (EncodeError)
1065{
1066        Get_port_number().SetFormat(Integer::AsciiDecimal);
1067}
1068
1069void SDP_media_port::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1070{
1071        Charstring csSlash;
1072        csSlash.SetValue("/");
1073
1074        if((field_id == id_num_of_ports) && IsPresent(id_num_of_ports)) {
1075                Get_num_of_ports().SetFormat(Integer::AsciiDecimal);
1076                csSlash.Encode(buffer);
1077        }
1078}
1079
1080void SDP_media_field::PostEncode (Buffer& buffer) throw (EncodeError)
1081{
1082        Charstring csCRLF;
1083        csCRLF.SetValue("\r\n");
1084
1085        csCRLF.Encode(buffer);
1086}
1087
1088void SDP_media_desc::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1089{
1090        Charstring csHeader;
1091
1092        if(IsPresent(field_id)) {
1093                switch(field_id) {
1094                case id_information:
1095                        csHeader.SetValue("i=");
1096                        csHeader.Encode(buffer);
1097                        break;         
1098                case id_key:
1099                        csHeader.SetValue("k=");
1100                        csHeader.Encode(buffer);
1101                        break;         
1102                }
1103        }
1104}
1105
1106void SDP_media_desc::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1107{
1108        Charstring csCRLF;
1109        csCRLF.SetValue("\r\n");
1110
1111        switch(field_id) {
1112        case id_information:
1113        case id_key:
1114                if(IsPresent(field_id)) {
1115                        csCRLF.Encode(buffer);
1116                }
1117                break;
1118        }
1119}
1120
1121void SDP_connection_list::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1122{
1123        Charstring csHeader;
1124
1125        csHeader.SetValue("c=");
1126        csHeader.Encode(buffer);
1127}
1128
1129void SDP_connection_list::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1130{
1131        Charstring csCRLF;
1132        csCRLF.SetValue("\r\n");
1133
1134        csCRLF.Encode(buffer);
1135}
1136
1137void SDP_key::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1138{
1139        Charstring csColon;
1140        csColon.SetValue(":");
1141
1142        if((field_id == id_key) && IsPresent(id_key)) {
1143                csColon.Encode(buffer);
1144        }
1145}
1146
1147void SDP_contact::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1148{
1149        Charstring csLeftPar, csSpace;
1150        csLeftPar.SetValue("(");
1151        csSpace.SetValue(" ");
1152       
1153        if((field_id == id_disp_name) && IsPresent(id_disp_name)) {
1154                csSpace.Encode(buffer);
1155                csLeftPar.Encode(buffer);
1156        }
1157}
1158
1159void SDP_contact::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1160{
1161        Charstring csRightPar;
1162        csRightPar.SetValue(")");
1163
1164        if((field_id == id_disp_name) && IsPresent(id_disp_name)) {
1165                csRightPar.Encode(buffer);
1166        }
1167}
1168
1169void SDP_repeat_list::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1170{
1171        Charstring csHeader;
1172
1173        csHeader.SetValue("r=");
1174        csHeader.Encode(buffer);
1175}
1176
1177void SDP_repeat_list::PostEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1178{
1179        Charstring csCRLF;
1180        csCRLF.SetValue("\r\n");
1181
1182        csCRLF.Encode(buffer);
1183}
1184
1185void SDP_repeat::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1186{
1187        Charstring csSpace;
1188        csSpace.SetValue(" ");
1189
1190        if(field_id == id_active) {
1191                csSpace.Encode(buffer);
1192        }
1193}
1194
1195void SDP_typed_time_list::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1196{
1197        Charstring csSpace;
1198        csSpace.SetValue(" ");
1199
1200        csSpace.Encode(buffer);
1201}
1202
1203void SDP_time_field::PreEncode (Buffer& buffer) throw (EncodeError)
1204{
1205        Charstring csHeader;
1206
1207        csHeader.SetValue("t=");
1208        csHeader.Encode(buffer);
1209}
1210
1211void SDP_time_field::PostEncode (Buffer& buffer) throw (EncodeError)
1212{
1213        Charstring csCRLF;
1214        csCRLF.SetValue("\r\n");
1215
1216        csCRLF.Encode(buffer);
1217}
1218
1219void SDP_time_field::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1220{
1221        Charstring csSpace;
1222        csSpace.SetValue(" ");
1223
1224        if(field_id == id_stop_time) {
1225                csSpace.Encode(buffer);
1226        }
1227}
1228
1229
1230
1231
1232
1233void SDP_attribute_cat::PreEncode (Buffer& buffer) throw (EncodeError)
1234{
1235        Charstring csAttrName;
1236        csAttrName.SetValue("cat:");
1237
1238        csAttrName.Encode(buffer);
1239}
1240
1241void SDP_attribute_keywds::PreEncode (Buffer& buffer) throw (EncodeError)
1242{
1243        Charstring csAttrName;
1244        csAttrName.SetValue("keywds:");
1245
1246        csAttrName.Encode(buffer);
1247}
1248
1249void SDP_attribute_tool::PreEncode (Buffer& buffer) throw (EncodeError)
1250{
1251        Charstring csAttrName;
1252        csAttrName.SetValue("tool:");
1253
1254        csAttrName.Encode(buffer);
1255}
1256
1257void SDP_attribute_ptime::PreEncode (Buffer& buffer) throw (EncodeError)
1258{
1259        Charstring csAttrName;
1260        csAttrName.SetValue("ptime:");
1261
1262        csAttrName.Encode(buffer);
1263}
1264
1265void SDP_attribute_recvonly::PreEncode (Buffer& buffer) throw (EncodeError)
1266{
1267        Charstring csAttrName;
1268        csAttrName.SetValue("recvonly");
1269
1270        csAttrName.Encode(buffer);
1271}
1272
1273void SDP_attribute_sendrecv::PreEncode (Buffer& buffer) throw (EncodeError)
1274{
1275        Charstring csAttrName;
1276        csAttrName.SetValue("sendrecv");
1277
1278        csAttrName.Encode(buffer);
1279}
1280
1281void SDP_attribute_sendonly::PreEncode (Buffer& buffer) throw (EncodeError)
1282{
1283        Charstring csAttrName;
1284        csAttrName.SetValue("sendonly");
1285
1286        csAttrName.Encode(buffer);
1287}
1288
1289void SDP_attribute_inactive::PreEncode (Buffer& buffer) throw (EncodeError)
1290{
1291        Charstring csAttrName;
1292        csAttrName.SetValue("inactive");
1293
1294        csAttrName.Encode(buffer);
1295}
1296
1297void SDP_attribute_orient::PreEncode (Buffer& buffer) throw (EncodeError)
1298{
1299        Charstring csAttrName;
1300        csAttrName.SetValue("orient:");
1301
1302        csAttrName.Encode(buffer);
1303}
1304
1305void SDP_attribute_type::PreEncode (Buffer& buffer) throw (EncodeError)
1306{
1307        Charstring csAttrName;
1308        csAttrName.SetValue("type:");
1309
1310        csAttrName.Encode(buffer);
1311}
1312
1313void SDP_attribute_charset::PreEncode (Buffer& buffer) throw (EncodeError)
1314{
1315        Charstring csAttrName;
1316        csAttrName.SetValue("charset:");
1317
1318        csAttrName.Encode(buffer);
1319}
1320
1321void SDP_attribute_sdplang::PreEncode (Buffer& buffer) throw (EncodeError)
1322{
1323        Charstring csAttrName;
1324        csAttrName.SetValue("sdplang:");
1325
1326        csAttrName.Encode(buffer);
1327}
1328
1329void SDP_attribute_lang::PreEncode (Buffer& buffer) throw (EncodeError)
1330{
1331        Charstring csAttrName;
1332        csAttrName.SetValue("lang:");
1333
1334        csAttrName.Encode(buffer);
1335}
1336
1337void SDP_attribute_framerate::PreEncode (Buffer& buffer) throw (EncodeError)
1338{
1339        Charstring csAttrName;
1340        csAttrName.SetValue("framerate:");
1341
1342        csAttrName.Encode(buffer);
1343}
1344
1345void SDP_attribute_quality::PreEncode (Buffer& buffer) throw (EncodeError)
1346{
1347        Charstring csAttrName;
1348        csAttrName.SetValue("quality:");
1349
1350        csAttrName.Encode(buffer);
1351}
1352
1353void SDP_attribute_fmtp::PreEncode (Buffer& buffer) throw (EncodeError)
1354{
1355        Charstring csAttrName;
1356        csAttrName.SetValue("fmtp:");
1357
1358        csAttrName.Encode(buffer);
1359}
1360
1361void SDP_attribute_curr::PreEncode (Buffer& buffer) throw (EncodeError)
1362{
1363        Charstring csAttrName;
1364        csAttrName.SetValue("curr:");
1365
1366        csAttrName.Encode(buffer);
1367}
1368
1369void SDP_attribute_curr::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1370{
1371        Charstring csSpace;
1372        csSpace.SetValue(" ");
1373       
1374        if(field_id != 0) {
1375                csSpace.Encode(buffer);
1376        }
1377}
1378
1379void SDP_attribute_des::PreEncode (Buffer& buffer) throw (EncodeError)
1380{
1381        Charstring csAttrName;
1382        csAttrName.SetValue("des:");
1383
1384        csAttrName.Encode(buffer);
1385}
1386
1387void SDP_attribute_des::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1388{
1389        Charstring csSpace;
1390        csSpace.SetValue(" ");
1391       
1392        if(field_id != 0) {
1393                csSpace.Encode(buffer);
1394        }
1395}
1396
1397void SDP_attribute_conf::PreEncode (Buffer& buffer) throw (EncodeError)
1398{
1399        Charstring csAttrName;
1400        csAttrName.SetValue("conf:");
1401
1402        csAttrName.Encode(buffer);
1403}
1404
1405void SDP_attribute_conf::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1406{
1407        Charstring csSpace;
1408        csSpace.SetValue(" ");
1409       
1410        if(field_id != 0) {
1411                csSpace.Encode(buffer);
1412        }
1413}
1414
1415void SDP_attribute_rtpmap::PreEncode (Buffer& buffer) throw (EncodeError)
1416{
1417        Charstring csAttrName;
1418        csAttrName.SetValue("rtpmap:");
1419
1420        csAttrName.Encode(buffer);
1421}
1422
1423void SDP_attribute_rtcp::PreEncode (Buffer& buffer) throw (EncodeError)
1424{
1425        Charstring csAttrName;
1426        csAttrName.SetValue("rtcp:");
1427
1428        csAttrName.Encode(buffer);
1429}
1430
1431void SDP_attribute_unknown::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
1432{
1433        Charstring csColon;
1434        csColon.SetValue(":");
1435
1436        if((field_id == id_attr_value) && IsPresent(id_attr_value)) {
1437                csColon.Encode(buffer);
1438        }
1439}
1440
1441
1442
1443
1444}} // namespaces
1445
Note: See TracBrowser for help on using the repository browser.