diff --git a/src/zutil/parser/sdp/MediaDescription.java b/src/zutil/parser/sdp/MediaDescription.java new file mode 100644 index 0000000..d373a97 --- /dev/null +++ b/src/zutil/parser/sdp/MediaDescription.java @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ziver Koc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package zutil.parser.sdp; + +import java.util.HashMap; +import java.util.Map; + +/** + * A data class containing information about a specific media + */ +public class MediaDescription { + protected String type; + protected int transportPort; + protected String transport; + + protected String label; + + protected Map attributes = new HashMap<>(); + + + public String getType() { + return type; + } + + public int getTransportPort() { + return transportPort; + } + + public String getTransport() { + return transport; + } + + public String getLabel() { + return label; + } +} \ No newline at end of file diff --git a/src/zutil/parser/sdp/SDPParser.java b/src/zutil/parser/sdp/SDPParser.java new file mode 100644 index 0000000..684f0b7 --- /dev/null +++ b/src/zutil/parser/sdp/SDPParser.java @@ -0,0 +1,233 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ziver Koc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ziver Koc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package zutil.parser.sdp; + +import zutil.io.IOUtil; +import zutil.io.StringInputStream; +import zutil.log.LogUtil; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +/** + * A parser class for reading SDP Media Session Description. + * The protocol describes a + * + * @see RFC2327 + */ +public class SDPParser { + public static final Logger logger = LogUtil.getLogger(); + + private InputStream in; + + + public SDPParser(InputStream in) { + this.in = in; + } + + public SDPParser(String input) { + this.in = new StringInputStream(input); + } + + /** + * Will read the stream until its end and create SessionDescription objects + * + * @return a List of sessions parsed from the InputStream. Empty list if no sessions where defined. + * @throws IOException if ther eis any IO related issues. + * @throws RuntimeException if there is any parsing issue. + */ + public List parse() throws IOException { + List sessions = new ArrayList<>(); + + String line; + SessionDescription currentSession = null; + TimingDescription currentTiming = null; + MediaDescription currentMedia = null; + String[] tmpArr; + + while ((line=IOUtil.readLine(in)) != null) { + if (line.trim().isEmpty()) + continue; + + if (line.length() > 2 && line.charAt(1) != '=') { + logger.warning("Payload contains invalid SDP format: '" + line + "'"); + continue; + } + + switch (line.charAt(0)) { + // -------------------------------------- + // Session description + // -------------------------------------- + + // v= // Start of a new session + case 'v': + currentSession = new SessionDescription(); + sessions.add(currentSession); + currentSession.protocolVersion = Integer.parseInt(getValue(line)); + break; + + // TODO: o=
+ + // s= + case 's': + if (currentSession == null) throw new RuntimeException("Received session title before session definition: '" + line + "'"); + + currentSession.sessionTitle = getValue(line); + break; + + // [optional] u= + case 'u': + if (currentSession == null) throw new RuntimeException("Received session URI before session definition: '" + line + "'"); + + currentSession.sessionURI = getValue(line); + break; + + // [optional] e= + case 'e': + if (currentSession == null) throw new RuntimeException("Received organizer email before session definition: '" + line + "'"); + + currentSession.organizerEmail = getValue(line); + break; + + // [optional] p= + case 'p': + if (currentSession == null) throw new RuntimeException("Received organizer phone before session definition: '" + line + "'"); + + currentSession.organizerPhoneNumber = getValue(line); + break; + + // TODO: [optional] c=
// Session overall connection information + + // TODO: [optional] b=: + + // TODO: [optional] z= .... // Time zone adjustments + + // TODO: [optional] k=: // Encryption information + + // -------------------------------------- + // Time description + // -------------------------------------- + + // t= // Time the session is active + case 't': + if (currentSession == null) throw new RuntimeException("Time description received before a session has been defined: '" + line + "'"); + + currentTiming = new TimingDescription(); + currentSession.timing.add(currentTiming); + + tmpArr = getValueArray(line); + if (tmpArr.length != 2) throw new RuntimeException("Incorrect time definition found: '" + line + "'"); + + currentTiming.startTime = Long.parseLong(tmpArr[0]); + currentTiming.endTime = Long.parseLong(tmpArr[1]); + break; + + // TODO: [optional] r= // Repeat information + + // -------------------------------------- + // Media description + // -------------------------------------- + + // m= // Media name and transport address + case 'm': + if (currentSession == null) throw new RuntimeException("Media description received before a session has been defined"); + + currentMedia = new MediaDescription(); + currentSession.media.add(currentMedia); + + tmpArr = getValueArray(line); + if (tmpArr.length < 3) throw new RuntimeException("Incorrect media definition found: '" + line + "'"); + + currentMedia.type = tmpArr[0]; + currentMedia.transportPort = Integer.parseInt(tmpArr[1]); // TODO: Support "/" notation + currentMedia.transport = tmpArr[2]; + // TODO: Support media formats + break; + + // [optional] i= + // [optional] i= + case 'i': + if (currentSession == null) throw new RuntimeException("Received session title before session definition: '" + line + "'"); + + if (currentMedia != null) + currentMedia.label = getValue(line); + else + currentSession.sessionDescription = getValue(line); + break; + + // TODO: [optional] c=
// Media specific connection information + + // TODO: [optional] b=(bandwidth information) + + // TODO: [optional] k=(encryption key) + + // Zero or more session attribute lines + // TODO: [optional] a=: + // TODO: [optional] a=: + // TODO: [optional] a=rtpmap:: + + default: + logger.fine("Unknown announcement type '" + line + "'"); + } + } + + return sessions; + } + + private String getValue(String line) { + return line.substring(2); + } + + private String[] getValueArray(String line) { + return getValue(line).split(" "); + } +} diff --git a/src/zutil/parser/sdp/SessionDescription.java b/src/zutil/parser/sdp/SessionDescription.java new file mode 100644 index 0000000..db43ec3 --- /dev/null +++ b/src/zutil/parser/sdp/SessionDescription.java @@ -0,0 +1,93 @@ +package zutil.parser.sdp; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A data class containing information about a Media session + */ +public class SessionDescription { + protected int protocolVersion; + + protected String sessionOwner; + protected String sessionId; + protected String sessionVersion; + protected String networkType; + protected String addressType; + protected String address; + + protected String sessionTitle; + protected String sessionDescription; + protected String sessionURI; + + protected String organizerEmail; + protected String organizerPhoneNumber; + + protected List timing = new ArrayList<>(); + + protected List media = new ArrayList<>(); + + protected Map attributes = new HashMap<>(); + + + public int getProtocolVersion() { + return protocolVersion; + } + + public String getSessionOwner() { + return sessionOwner; + } + + public String getSessionId() { + return sessionId; + } + + public String getSessionVersion() { + return sessionVersion; + } + + public String getNetworkType() { + return networkType; + } + + public String getAddressType() { + return addressType; + } + + public String getAddress() { + return address; + } + + public String getSessionTitle() { + return sessionTitle; + } + + public String getSessionDescription() { + return sessionDescription; + } + + public String getSessionURI() { + return sessionURI; + } + + public String getOrganizerEmail() { + return organizerEmail; + } + + public String getOrganizerPhoneNumber() { + return organizerPhoneNumber; + } + + public List getTiming() { + return timing; + } + + public List getMedia() { + return media; + } +} + + + diff --git a/src/zutil/parser/sdp/TimingDescription.java b/src/zutil/parser/sdp/TimingDescription.java new file mode 100644 index 0000000..97c7486 --- /dev/null +++ b/src/zutil/parser/sdp/TimingDescription.java @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ziver Koc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package zutil.parser.sdp; + +/** + * A data class containing information timing information about a media session + */ +public class TimingDescription { + protected long startTime; + protected long endTime; + + // repeat information + + + public long getStartTime() { + return startTime; + } + + public long getEndTime() { + return endTime; + } +} \ No newline at end of file