/** * */ package video.lib; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.net.URI; import java.net.URISyntaxException; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.util.LinkedHashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * All heads for an RTSP message, including general and entity headers. For RTSP * request message, this also includes request header. For RTSP response * message, this also includes response header. * * @see RFC 2326 [6] and RFC 2616 [4.2]. * @author yuezhu * */ public abstract class RtspMessage { protected static final String CRLF = "\r\n"; protected static final String SP = " "; protected static final String VERSION = "RTSP/1.0"; public enum Type { REQUEST, RESPONSE, NONE; } public RtspMessage() { this.headers = new LinkedHashMap<String, String>(); this.body = new StringBuilder(); } // RTSP headers. private Map<String, String> headers = null; // RTSP body. StringBuilder body = null; // RTSP message type. private Type type = Type.NONE; public Type getType() { return type; } public void setType(Type type) { this.type = type; } public Map<String, String> getHeader() { return headers; } /** * @see RFC 2616 [14.45] */ public void setProxy() { String s = Configuration.getProductTokens(); if (headers.get("Server") != null) { headers.put("Via", s); } else { headers.put("Server", s); } // headers.put("Via", s); } public String getField(String name) { return headers.get(name); } public void setField(String name, String value) { headers.put(name, value); } public boolean containsField(String name) { return headers.containsKey(name); } public StringBuilder getBody() { return body; } public void setBody(StringBuilder body) { this.body = body; } public void appendBody(StringBuilder value) { body.append(value); } public void appendBody(String value) { body.append(value); } public void appendBody(CharBuffer value) { body.append(value); } public int getBodyLength() { return body.length(); } @Override abstract public String toString(); //////// // RTSP request pattern. protected static final Pattern RtspRequestPattern = Pattern.compile(new StringBuilder() .append("(") .append(RtspMethod.getRegex()) .append(")") .append(" ") .append("(\\*|[^\\s]+)") .append(" ") .append("(RTSP/1.0)") .toString()); // RTSP response pattern. protected static final Pattern RtspResponsePattern = Pattern.compile(new StringBuilder() .append("(RTSP/1.0)") .append(" ") .append("([1-5][\\d]*)") .append(" ") .append("(.*)") .toString()); // RTSP message header pattern. protected static final Pattern RtspHeaderPattern = Pattern.compile(new StringBuilder() .append("([\\w]+[\\-\\w]*)") .append(":\\s?") .append("(.+)") .toString()); public static RtspMessage parse(CharBuffer in) { if (in == null) { return null; } BufferedReader rdr = new BufferedReader(new StringReader(in.toString())); return parse(rdr); } public static RtspMessage parse(String in) { if (in == null) { return null; } BufferedReader rdr = new BufferedReader(new StringReader(in)); return parse(rdr); } public static RtspMessage parse(byte[] in) { if (in == null) { return null; } InputStream is = new ByteArrayInputStream(in); BufferedReader rdr = new BufferedReader(new InputStreamReader(is, Charset.forName(Constants.CHARSET))); return parse(rdr); } public static RtspMessage parse(BufferedReader rdr) { RtspMessage message = null; try { String line = null; Matcher matcher = null; // first line. line = rdr.readLine(); if (line.startsWith(RtspMessage.VERSION)) { // It is an RTSP response. message = new RtspResponse(); matcher = RtspResponsePattern.matcher(line); if (!matcher.matches()) { // Request line is ill-formatted. return null; } ((RtspResponse) message).setStatusCode(RtspStatusCode.fromCode(matcher.group(2))); } else { // It is an RTSP request. message = new RtspRequest(); matcher = RtspRequestPattern.matcher(line); if (!matcher.matches()) { // Status line is ill-formatted. return null; } ((RtspRequest) message).setMethod(RtspMethod.fromString(matcher.group(1))); String uriString = matcher.group(2); if (uriString.equals("*")) { ((RtspRequest) message).setRequestUri(null); } else { URI uri = new URI(uriString); ((RtspRequest) message).setRequestUri(uri); } } while ((line = rdr.readLine()) != null && (!line.equals(""))) { matcher = RtspHeaderPattern.matcher(line); if (!matcher.matches()) { // Header line is ill-formatted. return null; } // Set each parsed field into message header. message.setField(matcher.group(1), matcher.group(2)); } while ((line = rdr.readLine()) != null && (!line.equals(""))) { message.appendBody(line); message.appendBody(RtspMessage.CRLF); } rdr.close(); return message; } catch (URISyntaxException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } return null; } }