Browse code

rtp_media_server: improve payload sdp parsing

Julien Chavanton authored on 09/05/2019 04:22:55
Showing 4 changed files
... ...
@@ -226,12 +226,11 @@ rms_dialog_info_t *rms_dialog_new(struct sip_msg *msg)
226 226
 	rms_sdp_info_t *sdp_info = &si->sdp_info_offer;
227 227
 	if(!rms_get_sdp_info(sdp_info, msg))
228 228
 		goto error;
229
-	si->media.pt = rms_sdp_check_payload(sdp_info);
229
+	si->media.pt = rms_sdp_select_payload(sdp_info);
230 230
 	if(!si->media.pt) {
231 231
 		tmb.t_reply(msg, 488, "incompatible media format");
232 232
 		goto error;
233 233
 	}
234
-	//if(!create_session_payload(&si->media)) goto error;
235 234
 	clist_init(&si->action, next, prev);
236 235
 	return si;
237 236
 error:
... ...
@@ -134,7 +134,7 @@ void rms_sdp_info_free(rms_sdp_info_t *sdp_info)
134 134
 	}
135 135
 }
136 136
 
137
-int rms_sdp_prepare_new_body(rms_sdp_info_t *sdp_info, int payload_type_number)
137
+int rms_sdp_prepare_new_body(rms_sdp_info_t *sdp_info, PayloadType *pt)
138 138
 {
139 139
 	if(sdp_info->new_body.s)
140 140
 		return 0;
... ...
@@ -154,13 +154,16 @@ int rms_sdp_prepare_new_body(rms_sdp_info_t *sdp_info, int payload_type_number)
154 154
 	body->len += strlen(sdp_c);
155 155
 
156 156
 	char sdp_m[128];
157
-	snprintf(sdp_m, 128, "m=audio %d RTP/AVP %d\r\n", sdp_info->udp_local_port,
158
-			payload_type_number);
157
+	snprintf(sdp_m, 128, "m=audio %d RTP/AVP %d\r\n", sdp_info->udp_local_port, pt->type);
159 158
 	body->len += strlen(sdp_m);
160 159
 
161
-	char sdp_a[128]; // Opus always 48Khz in RTP and always stereo
162
-	if (payload_type_number >= 96) {
163
-		snprintf(sdp_a, 128, "a=rtpmap:%d opus/48000/2\r\n", payload_type_number);
160
+	char sdp_a[128];
161
+	if (pt->type >= 96) {
162
+		if (strcasecmp(pt->mime_type,"opus") == 0) {
163
+			snprintf(sdp_a, 128, "a=rtpmap:%d opus/48000/2\r\n", pt->type);
164
+		} else {
165
+			snprintf(sdp_a, 128, "a=rtpmap:%d %s/%d/%d\r\n", pt->type, pt->mime_type, pt->clock_rate, pt->channels);
166
+		}
164 167
 		body->len += strlen(sdp_a);
165 168
 	}
166 169
 
... ...
@@ -174,89 +177,92 @@ int rms_sdp_prepare_new_body(rms_sdp_info_t *sdp_info, int payload_type_number)
174 177
 	strcat(body->s, sdp_t);
175 178
 	strcat(body->s, sdp_m);
176 179
 
177
-	if (payload_type_number >= 96) {
180
+	if (pt->type >= 96) {
178 181
 		strcat(body->s, sdp_a);
179 182
 	}
180 183
 	return 1;
181 184
 }
182 185
 
183 186
 PayloadType *
184
-rms_payload_type_new() // TODO: convert at the last minute from the MS manager process instead.
187
+rms_payload_type_new() // This could be problematic as it must remain compatible with the constructor in MS2.
185 188
 {
186 189
 	PayloadType *newpayload = (PayloadType *)shm_malloc(sizeof(PayloadType));
187 190
 	newpayload->flags |= PAYLOAD_TYPE_ALLOCATED;
191
+	memset(newpayload, 0, sizeof(PayloadType));
188 192
 	return newpayload;
189 193
 }
190 194
 
191
-PayloadType *rms_sdp_check_payload(rms_sdp_info_t *sdp)
195
+PayloadType *rms_sdp_check_payload_type(PayloadType *pt, rms_sdp_info_t *sdp)
192 196
 {
193
-	// https://tools.ietf.org/html/rfc3551
194
-	LM_INFO("payloads[%s]\n", sdp->payloads.s); // 0 8
195
-	PayloadType *pt = rms_payload_type_new();
196
-	char *payloads = sdp->payloads.s;
197
-	char *payload_type_number = strtok(payloads, " ");
198
-	if(!payload_type_number) {
199
-		shm_free(pt); // payload_type_destroy(pt);
200
-		return NULL;
201
-	}
202
-	pt->type = atoi(payload_type_number);
203 197
 	pt->clock_rate = 8000;
204 198
 	pt->channels = 1;
205 199
 	pt->mime_type = NULL;
206
-	while(!pt->mime_type) {
207
-		if(pt->type > 127) {
200
+	if (pt->type > 127) {
201
+		return NULL;
202
+	} else if (pt->type >= 96) {
203
+		char *rtpmap = rms_sdp_get_rtpmap(sdp->recv_body, pt->type);
204
+		if (!rtpmap) return NULL;
205
+		char *s_mime_type = strtok(rtpmap,"/");
206
+		if (!s_mime_type) {
207
+			shm_free(rtpmap);
208 208
 			return NULL;
209
-		} else if (pt->type >= 96) {
210
-			char *rtpmap = rms_sdp_get_rtpmap(sdp->recv_body, pt->type);
211
-			if (!rtpmap) return NULL;
212
-			char *s_mime_type = strtok(rtpmap,"/");
213
-			if (!s_mime_type) {
214
-				shm_free(rtpmap);
215
-				return NULL;
209
+		}
210
+		if (strcasecmp(s_mime_type,"opus") == 0) {
211
+			int payload_type = pt->type;
212
+			memcpy(pt, &payload_type_opus, sizeof(PayloadType));
213
+			pt->type = payload_type;
214
+			char * s_clock_rate = strtok(NULL,"/");
215
+			char * s_channels = strtok(NULL,"/");
216
+			if (s_clock_rate) {
217
+				pt->clock_rate = atoi(s_clock_rate);
218
+			} else {
219
+				pt->clock_rate = 8000;
216 220
 			}
217
-			if (strcasecmp(s_mime_type,"opus") == 0) {
218
-				int payload_type = pt->type;
219
-				memcpy(pt, &payload_type_opus, sizeof(PayloadType));
220
-				pt->type = payload_type;
221
-				char * s_clock_rate = strtok(NULL,"/");
222
-				char * s_channels = strtok(NULL,"/");
223
-				if (s_clock_rate) {
224
-					pt->clock_rate = atoi(s_clock_rate);
225
-				} else {
226
-					pt->clock_rate = 8000;
227
-				}
228
-				if (s_channels) {
229
-					pt->channels = atoi(s_channels);
230
-				} else {
231
-					pt->channels = 2;
232
-				}
233
-				shm_free(rtpmap);
234
-				LM_INFO("[%p][%d][%s|%d|%d]\n", pt, pt->type, pt->mime_type, pt->clock_rate, pt->channels);
235
-				return pt;
221
+			if (s_channels) {
222
+				pt->channels = atoi(s_channels);
223
+			} else {
224
+				pt->channels = 2;
236 225
 			}
237
-			shm_free(pt->mime_type);
238 226
 			shm_free(rtpmap);
239
-			pt->mime_type=NULL;
240
-			LM_INFO("unsuported codec\n");
241
-			return NULL;
242
-		} else if(pt->type == 0) {
243
-			pt->mime_type = rms_char_dup("pcmu", 1); /* ia=rtpmap:0 PCMU/8000*/
244
-		} else if(pt->type == 8) {
245
-			pt->mime_type = rms_char_dup("pcma", 1);
246
-		}
247
-		//	} else if (pt->type == 9) {
248
-		//		pt->mime_type=rms_char_dup("g722", 1);
249
-		//	} else if (pt->type == 18) {
250
-		//		pt->mime_type=rms_char_dup("g729", 1);
251
-		//	}
252
-		if(pt->mime_type)
253
-			break;
254
-		payload_type_number = strtok(NULL, " ");
255
-		if(!payload_type_number) {
256
-			shm_free(pt); // payload_type_destroy(pt);
257
-			return NULL;
227
+			LM_INFO("[%p][%d][%s|%d|%d]\n", pt, pt->type, pt->mime_type, pt->clock_rate, pt->channels);
228
+			return pt;
258 229
 		}
230
+		shm_free(pt->mime_type);
231
+		shm_free(rtpmap);
232
+
233
+	} else if (pt->type == 0) {
234
+		pt->mime_type = rms_char_dup("pcmu", 1); /* ia=rtpmap:0 PCMU/8000*/
235
+	} else if (pt->type == 8) {
236
+		pt->mime_type = rms_char_dup("pcma", 1);
237
+	}
238
+	//	} else if (pt->type == 9) {
239
+	//		pt->mime_type=rms_char_dup("g722", 1);
240
+	//	} else if (pt->type == 18) {
241
+	//		pt->mime_type=rms_char_dup("g729", 1);
242
+	//	}
243
+	if (pt->mime_type)
244
+		return pt;
245
+	return NULL;
246
+}
247
+
248
+PayloadType *rms_sdp_select_payload(rms_sdp_info_t *sdp)
249
+{
250
+	// https://tools.ietf.org/html/rfc3551
251
+	LM_INFO("payloads[%s]\n", sdp->payloads.s); // 0 8
252
+	PayloadType *pt = rms_payload_type_new();
253
+	char *payloads = sdp->payloads.s;
254
+	char *payload_type_number = strtok(payloads, " ");
255
+
256
+	while (payload_type_number) {
259 257
 		pt->type = atoi(payload_type_number);
258
+		pt = rms_sdp_check_payload_type(pt, sdp);
259
+		if (pt) return pt;
260
+		payload_type_number = strtok(NULL, " ");
261
+	}
262
+	if (!pt->mime_type) {
263
+		LM_INFO("unsuported codec\n");
264
+		if (pt) shm_free(pt); // payload_type_destroy(pt);
265
+		return NULL;
260 266
 	}
261 267
 	LM_INFO("payload_type:%d %s/%d/%d\n", pt->type, pt->mime_type,
262 268
 			pt->clock_rate, pt->channels);
... ...
@@ -38,10 +38,10 @@ typedef struct rms_sdp_info
38 38
 
39 39
 int rms_get_sdp_info(rms_sdp_info_t *sdp_info, struct sip_msg *msg);
40 40
 int rms_sdp_set_body(struct sip_msg *msg, str *new_body);
41
-int rms_sdp_prepare_new_body(rms_sdp_info_t *, int payload_type_number);
41
+int rms_sdp_prepare_new_body(rms_sdp_info_t *, PayloadType *);
42 42
 void rms_sdp_info_init(rms_sdp_info_t *sdp_info);
43 43
 int rms_sdp_info_clone(rms_sdp_info_t *dst, rms_sdp_info_t *src);
44 44
 void rms_sdp_info_free(rms_sdp_info_t *sdp_info);
45
-PayloadType *rms_sdp_check_payload(rms_sdp_info_t *);
45
+PayloadType *rms_sdp_select_payload(rms_sdp_info_t *);
46 46
 
47 47
 #endif
... ...
@@ -534,7 +534,7 @@ static void bridge_cb(struct cell *ptrans, int ntype, struct tmcb_params *pcbp)
534 534
 		LM_ERR("can not get SDP information\n");
535 535
 		goto error;
536 536
 	}
537
-	di->media.pt = rms_sdp_check_payload(sdp_info);
537
+	di->media.pt = rms_sdp_select_payload(sdp_info);
538 538
 	rms_update_media_sockets(pcbp->rpl, di, &di->sdp_info_answer);
539 539
 	LM_INFO("[%p][%s:%d]\n", di, sdp_info->local_ip.s,
540 540
 			sdp_info->udp_local_port);
... ...
@@ -554,7 +554,7 @@ static int rms_bridged_call(rms_dialog_info_t *di, rms_action_t *a)
554 554
 	sdp_info->local_ip.s = di->local_ip.s;
555 555
 	sdp_info->local_ip.len = di->local_ip.len;
556 556
 
557
-	rms_sdp_prepare_new_body(sdp_info, di->bridged_di->media.pt->type);
557
+	rms_sdp_prepare_new_body(sdp_info, di->bridged_di->media.pt);
558 558
 	rms_answer_call(a->cell, di, sdp_info);
559 559
 	LM_NOTICE("si_1[%p] si_2[%p]\n", di, di->bridged_di);
560 560
 	create_call_leg_media(&di->media);
... ...
@@ -685,7 +685,7 @@ static rms_dialog_info_t *rms_dialog_create_leg(rms_dialog_info_t *di, struct si
685 685
 		goto error;
686 686
 
687 687
 	rms_update_media_sockets(msg, di->bridged_di, &di->bridged_di->sdp_info_offer);
688
-	rms_sdp_prepare_new_body(&di->bridged_di->sdp_info_offer, di->media.pt->type);
688
+	rms_sdp_prepare_new_body(&di->bridged_di->sdp_info_offer, di->media.pt);
689 689
 	clist_init(&di->bridged_di->action, next, prev);
690 690
 	return di->bridged_di;
691 691
 error:
... ...
@@ -871,7 +871,7 @@ static int rms_bridge_f(struct sip_msg *msg, char *_target, char *_route)
871 871
 	// Prepare the body of the SDP offer for the current Payload type
872 872
 	// Both call legs will have the same offer.
873 873
 	LM_NOTICE("payload[%d]\n", di->media.pt->type);
874
-	rms_sdp_prepare_new_body(&di->sdp_info_offer, di->media.pt->type);
874
+	rms_sdp_prepare_new_body(&di->sdp_info_offer, di->media.pt);
875 875
 
876 876
 	// create b_leg
877 877
 	di->bridged_di = rms_dialog_create_leg(di, msg);
... ...
@@ -1104,7 +1104,7 @@ static int rms_answer_f(struct sip_msg *msg, char * _route)
1104 1104
 	tmb.t_get_reply_totag(msg, &to_tag);
1105 1105
 	rms_str_dup(&di->local_tag, &to_tag, 1);
1106 1106
 	LM_INFO("local_uri[%s]local_tag[%s]\n", di->local_uri.s, di->local_tag.s);
1107
-	if(!rms_sdp_prepare_new_body(&di->sdp_info_offer, di->media.pt->type)) {
1107
+	if(!rms_sdp_prepare_new_body(&di->sdp_info_offer, di->media.pt)) {
1108 1108
 		LM_ERR("error preparing SDP body\n");
1109 1109
 		goto error;
1110 1110
 	}