1 /*
2  * Copyright (C) 2002-2003 Fhg Fokus
3  *
4  * This file is part of SEMS, a free SIP media server.
5  *
6  * SEMS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version. This program is released under
10  * the GPL with the additional exemption that compiling, linking,
11  * and/or using OpenSSL is allowed.
12  *
13  * For a license to use the SEMS software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * SEMS is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 
28 #ifndef __SdpParser__
29 #define __SdpParser__
30 
31 #include <string>
32 #include <map>
33 #include <vector>
34 #include <netinet/in.h>
35 #include "AmPlugIn.h"
36 #include <memory>
37 using std::string;
38 
39 
40 #define COMFORT_NOISE_PAYLOAD_TYPE 13 // RFC 3389
41 #define DYNAMIC_PAYLOAD_TYPE_START 96 // range: 96->127, see RFC 1890
42 /**
43  * @file AmSdp.h
44  * Definitions for the SDP parser.
45  * Refer to the SDP RFC document for any further information.
46  */
47 
48 /** Scratch buffer size. */
49 #define BUFFER_SIZE 4096
50 
51 /** network type */
52 enum NetworkType { NT_OTHER=0, NT_IN };
53 /** address type */
54 enum AddressType { AT_NONE=0, AT_V4, AT_V6 };
55 /** media type */
56 enum MediaType { MT_NONE=0, MT_AUDIO, MT_VIDEO, MT_APPLICATION, MT_TEXT, MT_MESSAGE, MT_IMAGE };
57 /** transport protocol */
58 enum TransProt { TP_NONE=0, TP_RTPAVP, TP_RTPAVPF, TP_UDP, TP_RTPSAVP, TP_UDPTL, TP_RTPSAVPF, TP_UDPTLSRTPSAVP, TP_UDPTLSRTPSAVPF };
59 
60 /** \brief c=... line in SDP*/
61 struct SdpConnection
62 {
63   /** @see NetworkType */
64   int network;
65   /** @see AddressType */
66   int addrType;
67 
68   struct sockaddr_in ipv4;
69   struct sockaddr_in6 ipv6;
70   /** IP address */
71   string address;
72 
73   SdpConnection();
74 
75   bool operator == (const SdpConnection& other) const;
76   /** pretty print */
77   string debugPrint() const;
78 };
79 
80 /** \brief o=... line in SDP */
81 struct SdpOrigin
82 {
83   string user;
84   unsigned int sessId;
85   unsigned int sessV;
86   SdpConnection conn;
87 
SdpOriginSdpOrigin88   SdpOrigin() : user(), conn() {}
89 
SdpOriginSdpOrigin90   SdpOrigin(const SdpOrigin& other)
91     : user(other.user), sessId(other.sessId), sessV(other.sessV),
92       conn(other.conn)
93   {}
94 
95   bool operator == (const SdpOrigin& other) const;
96 };
97 /**
98  * \brief sdp payload
99  *
100  * this binds together pt, name, rate and parameters
101  */
102 struct SdpPayload
103 {
104   int    type;   // media type
105   int    payload_type; // SDP payload type
106   string encoding_name;
107   int    clock_rate; // sample rate (Hz)
108   string format;
109   string sdp_format_parameters;
110   int    encoding_param;
111 
SdpPayloadSdpPayload112   SdpPayload()
113     : payload_type(-1),
114       clock_rate(-1),
115       encoding_param(-1)
116   {}
117 
SdpPayloadSdpPayload118   SdpPayload(int pt)
119     : payload_type(pt),
120       clock_rate(-1),
121       encoding_param(-1)
122   {}
123 
SdpPayloadSdpPayload124   SdpPayload(int pt, const string& name, int rate, int param)
125     : payload_type(pt), encoding_name(name),
126       clock_rate(rate), encoding_param(param)
127   {}
128 
SdpPayloadSdpPayload129   SdpPayload(const SdpPayload& other)
130     : type(other.type), payload_type(other.payload_type),
131       encoding_name(other.encoding_name), clock_rate(other.clock_rate),
132       format(other.format), sdp_format_parameters(other.sdp_format_parameters),
133       encoding_param(other.encoding_param)
134   {}
135 
136   bool operator == (int r);
137 
138   bool operator == (const SdpPayload& other) const;
139 };
140 
141 /** \brief a=... line in SDP */
142 struct SdpAttribute
143 {
144   string attribute;
145   string value;
146 
147   // property attribute
SdpAttributeSdpAttribute148   SdpAttribute(const string& attribute,
149 	       const string& value)
150     : attribute(attribute), value(value) { }
151 
152   // value attribute
SdpAttributeSdpAttribute153   SdpAttribute(const string& attribute)
154     : attribute(attribute) { }
155 
SdpAttributeSdpAttribute156   SdpAttribute(const SdpAttribute& other)
157     : attribute(other.attribute), value(other.value) {}
158 
159   string print() const;
160 
161   bool operator == (const SdpAttribute& other) const;
162 };
163 
164 /** \brief m=... line in SDP */
165 struct SdpMedia
166 {
167   enum Direction {
168     DirBoth=0,
169     DirActive=1,
170     DirPassive=2,
171     DirUndefined=3
172   };
173 
174   int           type;
175   unsigned int  port;
176   unsigned int  nports;
177   int           transport;
178   SdpConnection conn; // c=
179   Direction     dir;  // a=direction
180   string        fmt;  // format in case proto != RTP/AVP or RTP/SAVP
181 
182   // sendrecv|sendonly|recvonly|inactive
183   bool          send;
184   bool          recv;
185 
186   std::vector<SdpPayload> payloads;
187 
188   std::vector<SdpAttribute> attributes; // unknown attributes
189 
190   bool operator == (const SdpMedia& other) const;
191 
SdpMediaSdpMedia192   SdpMedia() : type(MT_NONE), transport(TP_NONE), conn(), dir(DirUndefined), send(true), recv(true) {}
193 
194   /** pretty print */
195   string debugPrint() const;
196 
197   static string type2str(int type);
198 
199   /**
200    * Checks which payloads are compatible with the payload provider,
201    * inserts them into the answer, compute send/recv attributes
202    * and direction according to the offer.
203    */
204   void calcAnswer(const AmPayloadProvider* payload_prov,
205 		  SdpMedia& answer) const;
206 };
207 
208 /**
209  * \brief handling SDP attribute "rtcp"
210  */
211 class RtcpAddress
212 {
213   private:
214     string nettype, addrtype, address;
215     bool parse(const string &src);
216     int port;
217 
218   public:
219     RtcpAddress(const string &attr_value);
hasAddress()220     bool hasAddress() { return !address.empty(); }
setAddress(const string & addr)221     void setAddress(const string &addr) { address = addr; }
getAddress()222     const string& getAddress() { return address; }
setPort(int _port)223     void setPort(int _port) { port = _port; }
getPort()224     int getPort() { return port; }
225     string print();
226 };
227 
228 /**
229  * \brief The SDP parser class.
230  */
231 class AmSdp
232 {
233 
234   /**
235    * Find payload by name, return cloned object
236    */
237   const SdpPayload *findPayload(const string& name) const;
238 
239 public:
240   // parsed SDP definition
241   unsigned int     version;     // v=
242   SdpOrigin        origin;      // o=
243   string           sessionName; // s=
244   string           uri;         // u=
245   SdpConnection    conn;        // c=
246   std::vector<SdpAttribute> attributes; // unknown session level attributes
247 
248   std::vector<SdpMedia> media;  // m= ... [a=rtpmap:...]+
249   //TODO: t= lines
250 
251   SdpOrigin        l_origin;      // local origin (o= )
252 
253   AmSdp();
254   AmSdp(const AmSdp& p_sdp_msg);
255 
256   /**
257    * Parse the SDP message passed as an argument.
258    * @return !=0 if error encountered.
259    */
260   int parse(const char* _sdp_msg);
261 
262   /**
263    * Prints the current SDP structure
264    * into a proper SDP message.
265    */
266   void print(string& body) const;
267 
268   /** get telephone event payload */
269   const SdpPayload *telephoneEventPayload() const;
270 
271   /**
272    * Test if remote UA supports 'telefone_event'.
273    */
274   //bool hasTelephoneEvent();
275 
276   bool operator == (const AmSdp& other) const;
277 
278   /**
279    * Clear all parsed values.
280    */
281   void clear();
282 };
283 
284 #endif
285 
286 // Local Variables:
287 // mode:C++
288 // End:
289