Results 1 to 7 of 7

Thread: RTSP / RTMP compatability

  1. Default RTSP / RTMP compatability

    We have a live streaming application using RTMP working with the liverepeater functions that we want to also feed in RTSP sources. I have the following questions:

    1. Connection management. Currently I use the onConnect stuff to approve connections. When using RTSP is did not call the existing connect calls, how do I handle connection approval?

    2. Stream control. I control the streams that can be published by intercepting and modifying the publish command. How do I handle validating the publishing stream and rejecting it as needed.

    3. Playback. Playback should be transparent to the client reguardless of the source. In particular the play name should be the same so they do not have to know what the source is.

  2. #2

    Default

    You most likely are not going to like these answers but here you go:

    1. Connection management. Currently I use the onConnect stuff to approve connections. When using RTSP is did not call the existing connect calls, how do I handle connection approval?
    The RTSP/RTP stuff is treated differently. Authentication is done using standard TCP based authentication. We did this so we could support the standard methods for RSTP/RTP authentication. We support three modes of authentication; none, basic and digest (strongest method with passwords not sent in the clear). By default digest is turned on. The usernames and passwords are stored in conf/rtp.password. The onConnect handler is not called for these connections.

    2. Stream control. I control the streams that can be published by intercepting and modifying the publish command. How do I handle validating the publishing stream and rejecting it as needed.
    There is no API for this at this time. We are considering adding a parallel API for the RTSP command set that works similarily to the current RTMP commands/modules.

    3. Playback. Playback should be transparent to the client reguardless of the source. In particular the play name should be the same so they do not have to know what the source is.
    To work with all the RTSP/RTP based encoders that exist out there we adopted a mapping strategy for the stream name. In most RTSP/RTP encoders you can specify a stream name that usually ends with a .sdp extension. We decode the stream name as follows:

    [application]/[app-instance]/[stream-name]

    If only two path elements are present the mapping is (with the app-instance defaulting to _definst_):

    [application]/[stream-name]

    If only one path element is present the mapping is (with the application defaulting to _defapp_ and the app-instance defaulting to _definst_):

    [stream-name]

    I hope this helps.

    Charlie
    Last edited by charlie; 05-20-2008 at 01:15 PM.

  3. Default

    Some follow up questions.
    1. I noticed you have a interface for RTP authentication can I create a class that implements authentition using my rules? Using this I might be able to avoid number 2.
    1b. Since the onConnect is not called at the other event based triggers called? I need to be able to track then the session started / ended and the IOStats for the session.

    3. Do you automatically also look from a stream with .sdp appended or do the users have to add the .sdp extension?
    Last edited by Richard C; 05-20-2008 at 04:00 PM.

  4. #4

    Default

    1. I noticed you have a interface for RTP authentication can I create a class that implements authentition using my rules? Using this I might be able to avoid number 2.
    Sure, here are the two interfaces that need to be implemented:

    Code:
    public interface IAuthenticate
    {
    	public static final int PASSWORDFILEFORMAT_UNKNOWN = 0;
    	public static final int PASSWORDFILEFORMAT_CLEAR = 1;
    	
    	public abstract void init(AuthenticationItem authenticationItem);
    }
    
    public interface IAuthenticateRTSP
    {
    	public abstract boolean authenticateRTSP(RTPSession rtspSession, RTSPRequestMessage req, RTSPResponseMessages resp);
    }
    And here is the code for the basic authentication type:

    Code:
    public class AuthenticateBasic implements IAuthenticate, IAuthenticateRTSP
    {
    	private AuthenticationItem authenticationItem = null;
    	private boolean isAuthenticated = false;
    	private String realm = null;
    	private File passwordFile = null;
    	
    	public void init(AuthenticationItem authenticationItem)
    	{
    		this.authenticationItem = authenticationItem;
    		realm = this.authenticationItem.getProperties().getPropertyStr("realm", realm);
    		String passwordFileStr = this.authenticationItem.getProperties().getPropertyStr("passwordFile", null);
    		if (passwordFileStr != null)
    		{
    			passwordFileStr = SystemUtils.expandEnvironmentVariables(passwordFileStr);
    			passwordFile = new File(passwordFileStr);
    		}
    	}
    	
    	private String getAuthString()
    	{
    		String ret = "Basic";
    		if (this.realm != null)
    			ret += " realm=\""+this.realm+"\"";
    		return ret;
    	}
    	
    	public boolean authenticateRTSP(RTPSession rtspSession, RTSPRequestMessage req, RTSPResponseMessages resp)
    	{
    		if (isAuthenticated)
    			return true;
    		
    		boolean isValid = false;
    		String inAuthStr = req.getHeader("authorization");
    		if (inAuthStr != null)
    		{
    			inAuthStr = inAuthStr.trim();
    			if (inAuthStr.toLowerCase().startsWith("basic "))
    				inAuthStr = inAuthStr.substring(6);
    			inAuthStr = inAuthStr.trim();
    			byte[] authBytes = Base64.decode(inAuthStr);
    			String authStr = new String(authBytes);
    			
    			String username = null;
    			String password = null;
    			int cindex = authStr.indexOf(":");
    			if (cindex >= 0)
    			{
    				username = authStr.substring(0, cindex);
    				password = authStr.substring(cindex+1);
    			}
    			else
    				username = authStr;
    			
    			//System.out.println("AuthenticateBasic.authenticateRTSP: "+username+":"+password);
    			
    			AuthenticationPasswordFile filePtr = AuthenticationPasswordFiles.getInstance().getPasswordFile(passwordFile);
    			if (filePtr != null)
    			{
    				if (username != null && password != null)
    				{
    					String authPassword = filePtr.getPassword(username);
    					if (authPassword.equals(password))
    					{
    						isValid = true;
    						isAuthenticated = true;
    					}
    				}
    				else
    				{
    					if (filePtr.userExists(username) && filePtr.getPassword(username) == null)
    					{
    						isValid = true;
    						isAuthenticated = true;
    					}
    				}
    			}
    			else
    				WMSLoggerFactory.getLogger(AuthenticationPasswordFile.class).warn("AuthenticateBasic.authenticateRTSP: Password file not found: "+passwordFile);
    		}
    		
    		if (!isValid)
    		{
    			RTPRequestStatus status = new RTPRequestStatus();
    			RTSPStatics.setStatus(status, 401);
    			
    			RTSPResponseMessage message = new RTSPResponseMessage();
    			message.setResponseCode(status.getResponseCode());
    			message.setResponseMessage(status.getResponseMessage());
    			message.setHeader("WWW-Authenticate", getAuthString());
    			message.setCSeq(req.getCSeq());
    			message.setSession(rtspSession.getSessionId());
    			resp.addMessage(message);
    		}
    		
    		return isValid;
    	}
    
    }
    1b. Since the onConnect is not called are the other event based triggers called? I need to be able to track then the session started / ended and the IOStats for the session.
    No, there really isn't a great way to track these sessions yet. I will consider adding this API.

    3. Do you automatically also look from a stream with .sdp appended or do the users have to add the .sdp extension?
    The users have to add the .sdp extension. Nothing is automatically appended. There are encoders that do not require or use a .sdp extension. QuickTime Broadcaster is the only encoder that I know of that automatically adds the .sdp extension. Wirecast does not.

    Charlie
    Last edited by charlie; 05-20-2008 at 04:22 PM.

  5. #5

    Default

    Sorry for noob question, but I haven't found where to connect created class with Wowza?
    It will be ideal if this could be done programmatically.
    Trying to make my module "implements IAuthenticate, IAuthenticateRTSP" gave no results.

  6. #6
    Join Date
    Dec 2007
    Posts
    25,640

    Default

    You should be able to drop that right into a Wowza Class module.

    Richard

  7. #7

    Default

    Thank you for answer, Richard!
    My main fault was forgetting to change Authentication.xml .

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •