/
SdpUtils.java
138 lines (127 loc) · 5.74 KB
/
SdpUtils.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package org.mobicents.servlet.restcomm.util;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Vector;
import javax.sdp.Connection;
import javax.sdp.MediaDescription;
import javax.sdp.Origin;
import javax.sdp.SdpException;
import javax.sdp.SdpFactory;
import javax.sdp.SdpParseException;
import javax.sdp.SessionDescription;
//import org.mobicents.servlet.restcomm.annotations.concurrency.ThreadSafe;
/**
* @author Henrique Rosa (henrique.rosa@telestax.com)
*/
//@ThreadSafe
public class SdpUtils {
/**
* Patches an SDP description by trimming and making sure it ends with a new line.
*
* @param sdpDescription The SDP description to be patched.
* @return The patched SDP description
* @author hrosa
*/
public static String endWithNewLine(String sdpDescription) {
if (sdpDescription == null || sdpDescription.isEmpty()) {
throw new IllegalArgumentException("The SDP description cannot be null or empty");
}
return sdpDescription.trim().concat("\n");
}
@SuppressWarnings("unchecked")
public static String patch(final String contentType, final byte[] data, final String externalIp)
throws UnknownHostException, SdpException {
final String text = new String(data);
String patchedSdp = null;
if (contentType.equalsIgnoreCase("application/sdp")) {
final SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(text);
// Handle the connection at the session level.
fix(sdp.getConnection(), externalIp);
// https://github.com/Mobicents/RestComm/issues/149
fix(sdp.getOrigin(), externalIp);
// Handle the connections at the media description level.
final Vector<MediaDescription> descriptions = sdp.getMediaDescriptions(false);
for (final MediaDescription description : descriptions) {
fix(description.getConnection(), externalIp);
}
patchedSdp = sdp.toString();
} else {
String boundary = contentType.split(";")[1].split("=")[1];
String[] parts = text.split(boundary);
String sdpText = null;
for (String part : parts) {
if (part.contains("application/sdp")) {
sdpText = part.replaceAll("Content.*", "").replaceAll("--", "").trim();
}
}
final SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(sdpText);
fix(sdp.getConnection(), externalIp);
// https://github.com/Mobicents/RestComm/issues/149
fix(sdp.getOrigin(), externalIp);
// Handle the connections at the media description level.
final Vector<MediaDescription> descriptions = sdp.getMediaDescriptions(false);
for (final MediaDescription description : descriptions) {
fix(description.getConnection(), externalIp);
}
patchedSdp = sdp.toString();
}
return patchedSdp;
}
public static String getSdp(final String contentType, final byte[] data) throws SdpParseException {
final String text = new String(data);
String sdpResult = null;
if (contentType.equalsIgnoreCase("application/sdp")) {
final SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(text);
sdpResult = sdp.toString();
} else {
String boundary = contentType.split(";")[1].split("=")[1];
String[] parts = text.split(boundary);
String sdpText = null;
for (String part : parts) {
if (part.contains("application/sdp")) {
sdpText = part.replaceAll("Content.*", "").replaceAll("--", "").trim();
}
}
final SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(sdpText);
sdpResult = sdp.toString();
}
return sdpResult;
}
private static void fix(final Origin origin, final String externalIp) throws UnknownHostException, SdpException {
if (origin != null) {
if (Connection.IN.equals(origin.getNetworkType())) {
if (Connection.IP4.equals(origin.getAddressType())) {
final InetAddress address = InetAddress.getByName(origin.getAddress());
final String ip = address.getHostAddress();
if (!IPUtils.isRoutableAddress(ip)) {
origin.setAddress(externalIp);
}
}
}
}
}
private static void fix(final Connection connection, final String externalIp) throws UnknownHostException, SdpException {
if (connection != null) {
if (Connection.IN.equals(connection.getNetworkType())) {
if (Connection.IP4.equals(connection.getAddressType())) {
final InetAddress address = InetAddress.getByName(connection.getAddress());
final String ip = address.getHostAddress();
if (!IPUtils.isRoutableAddress(ip)) {
connection.setAddress(externalIp);
}
}
}
}
}
public static boolean isWebRTCSDP(final String contentType, final byte[] data) throws SdpParseException {
boolean isWebRTC = false;
if (contentType.equalsIgnoreCase("application/sdp")) {
String sdp = getSdp(contentType, data);
if (sdp != null && sdp.contains("RTP/SAVP") || sdp.contains("rtp/savp")
|| sdp.contains("RTP/SAVPF") || sdp.contains("rtp/savpf")) {
isWebRTC = true;
}
}
return isWebRTC;
}
}