Attempt to fix the IPv4/IPv6 problems once and for all
[deb_shairplay.git] / src / lib / sdp.c
CommitLineData
23e7e3ae
JVH
1/**
2 * Copyright (C) 2011-2012 Juho Vähä-Herttua
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 */
14
2340bcd3
JVH
15#include <stdlib.h>
16#include <string.h>
17#include <assert.h>
18
19#include "sdp.h"
20
21struct sdp_s {
22 char *data;
23
24 /* Actual SDP records */
25 const char *version;
26 const char *origin;
27 const char *connection;
28 const char *session;
29 const char *time;
30 const char *media;
31
32 /* Additional SDP records */
33 const char *rtpmap;
34 const char *fmtp;
35 const char *rsaaeskey;
36 const char *aesiv;
37 const char *min_latency;
38};
39
40static void
41parse_sdp_line(sdp_t *sdp, char *line)
42{
43 int len = strlen(line);
44 if (len < 2 || line[1] != '=') {
45 return;
46 }
47
48 switch (line[0]) {
49 case 'v':
50 sdp->version = &line[2];
51 break;
52 case 'o':
53 sdp->origin = &line[2];
54 break;
55 case 's':
56 sdp->session = &line[2];
57 break;
58 case 'c':
59 sdp->connection = &line[2];
60 break;
61 case 't':
62 sdp->time = &line[2];
63 break;
64 case 'm':
65 sdp->media = &line[2];
66 break;
67 case 'a':
68 {
69 char *key;
70 char *value;
71
72 /* Parse key and value */
73 key = &line[2];
74 value = strstr(line, ":");
75 if (!value) break;
76 *(value++) = '\0';
77
78 if (!strcmp(key, "rtpmap")) {
79 sdp->rtpmap = value;
80 } else if (!strcmp(key, "fmtp")) {
81 sdp->fmtp = value;
82 } else if (!strcmp(key, "rsaaeskey")) {
83 sdp->rsaaeskey = value;
84 } else if (!strcmp(key, "aesiv")) {
85 sdp->aesiv = value;
86 } else if (!strcmp(key, "min-latency")) {
87 sdp->min_latency = value;
88 }
89 break;
90 }
91 }
92}
93
94static void
95parse_sdp_data(sdp_t *sdp)
96{
97 int pos, len;
98
99 pos = 0;
100 len = strlen(sdp->data);
101 while (pos < len) {
102 int lfpos;
103
104 /* Find newline in string */
105 for (lfpos=pos; sdp->data[lfpos]; lfpos++) {
106 if (sdp->data[lfpos] == '\n') {
107 break;
108 }
109 }
110 if (sdp->data[lfpos] != '\n') {
111 break;
112 }
113
114 /* Replace newline with '\0' and parse line */
115 sdp->data[lfpos] = '\0';
116 if (lfpos > pos && sdp->data[lfpos-1] == '\r') {
117 sdp->data[lfpos-1] = '\0';
118 }
119 parse_sdp_line(sdp, sdp->data+pos);
120 pos = lfpos+1;
121 }
122}
123
124sdp_t *
125sdp_init(const char *sdpdata, int sdpdatalen)
126{
127 sdp_t *sdp;
128
129 sdp = calloc(1, sizeof(sdp_t));
130 if (!sdp) {
131 return NULL;
132 }
133
134 /* Allocate data buffer */
135 sdp->data = malloc(sdpdatalen+1);
136 if (!sdp->data) {
137 free(sdp);
138 return NULL;
139 }
140 memcpy(sdp->data, sdpdata, sdpdatalen);
141 sdp->data[sdpdatalen] = '\0';
142 parse_sdp_data(sdp);
143 return sdp;
144}
145
146void
147sdp_destroy(sdp_t *sdp)
148{
149 if (sdp) {
150 free(sdp->data);
151 free(sdp);
152 }
153}
154
155const char *
156sdp_get_version(sdp_t *sdp)
157{
158 assert(sdp);
159
160 return sdp->version;
161}
162
163const char *
164sdp_get_origin(sdp_t *sdp)
165{
166 assert(sdp);
167
168 return sdp->origin;
169}
170
171const char *
172sdp_get_session(sdp_t *sdp)
173{
174 assert(sdp);
175
176 return sdp->session;
177}
178
179const char *
180sdp_get_connection(sdp_t *sdp)
181{
182 assert(sdp);
183
184 return sdp->connection;
185}
186
187const char *
188sdp_get_time(sdp_t *sdp)
189{
190 assert(sdp);
191
192 return sdp->time;
193}
194
195const char *
196sdp_get_media(sdp_t *sdp)
197{
198 assert(sdp);
199
200 return sdp->media;
201}
202
203const char *
204sdp_get_rtpmap(sdp_t *sdp)
205{
206 assert(sdp);
207
208 return sdp->rtpmap;
209}
210
211const char *
212sdp_get_fmtp(sdp_t *sdp)
213{
214 assert(sdp);
215
216 return sdp->fmtp;
217}
218
219const char *
220sdp_get_rsaaeskey(sdp_t *sdp)
221{
222 assert(sdp);
223
224 return sdp->rsaaeskey;
225}
226
227const char *
228sdp_get_aesiv(sdp_t *sdp)
229{
230 assert(sdp);
231
232 return sdp->aesiv;
233}
234
235const char *
236sdp_get_min_latency(sdp_t *sdp)
237{
238 assert(sdp);
239
240 return sdp->min_latency;
241}
242