Page 1 of 3 123 LastLast
Results 1 to 10 of 24

Thread: Module for authorizing requests for all stream types - getting the client request url

  1. #1

    Default Module for authorizing requests for all stream types - getting the client request url

    I'm writing a module that will integrate wowza with a streaming media control panel we're building. This module will call one of our application's authorization service to determine if the user is authorized to view the content they're requesting. Our authorization service takes in 2 parameters:
    1. The user/client IP
    2. The original request string

    I'm almost done with this module, and have found a lot of useful information in this forum, but I'd like to check with you before I finalize a few things. My first question relates to getting the entire original client request URL. This was harder than it should be, and I had to do it differently for each stream type. Have a look at the following code blocks:

    HTTP Streams:
    For the http streams, I used the onHTTPSessionCreate event. I couldn't find an easy way to just get the client's request URL, so I had to piece it together like so:

    String hostName = httpSession.getHTTPHeader("host");
    int requestPort = httpSession.getServerPort();
    String relativeUri = httpSession.getUri();
    String queryStr = httpSession.getQueryStr();
    String requestPath = String.format("http://%s:%s/%s?%s", hostName, requestPort, relativeUri, queryStr);

    Is this the right way of getting the entire client request URL? If there is a better way, please let me know.


    RTSP Streams:
    RTSP streams are by far the easiest. I used the onRTPSessionCreate event for my auth logic, and here is the code I used to get the client request url:

    String requestPath = rtpSession.getUri();

    That's how it should be!...


    RTMP Streams:
    For RTMP streams, I had to create a class named StreamListener that implements the IMediaStreamActionNotify interface, and then in the module's onStreamCreate event, I added that listener. I had to do it this way because the URL is not availble for RTMP streams until the onplay event. So I overrode the onPlay event and had to do this to get the client's request URL:

    String streamSourceUri = client.getUri();
    String queryStr = stream.getQueryStr();
    String requestPath = String.format("%s/%s?%s", streamSourceUri, streamName, queryStr);
    (the streamName variable is a input parameter to the onPlay event)

    Is this the right way of getting the client's request URL for RTMP streams? If not, please let me know of the best way.

    I hate that I had to piece the URLs together for RTMP and HTTP streams. It's tougher than it should be, and you lose some stuff, like the file type prefix (mp4:/path1/path2). I wish there was an easier way to get the request URL in one shot.


    My second question relates to the client's IP address. The methods for getting the IP address are inconsistent.

    onHTTPSessionCreate:
    String ipAddressClient = httpSession.getIpAddress();
    This returns back an IPv6 address

    onRTPSessionCreate:
    String ipAddressClient = rtpSession.getIp();
    This returns back an IPv4 address

    onPlay:
    IClient client = stream.getClient();
    String ipAddressClient = client.getIp();
    This returns back an IPv6 address

    I need the client's IPv4 address. Is there any way to get that for RTMP and HTTP connections?

    Thanks,
    Sean
    Last edited by seanngreen; 02-06-2013 at 07:03 PM.

  2. #2

    Default

    Hi,

    For the first part, getting the request uri, how you are doing it is pretty much how it needs to be done. There are various reasons,

    rtsp is the easiest because there is just 1 request uri. The base uri does not change between each part of the request. Where your method might fall down is if someone connects to publish a stream using rtsp. There is an interface that listens for each of the rtsp connection steps. A play stream will fire a DESCRIBE event and a publish stream will fire an ANNOUNCE event. The interface is IRTSPActionNotify.

    rtmp is actually 2 separate requests. the first part is the connection which you can get any time after onConnect has fired. It can sometimes have it's own query string. The second part is the stream request. This can also have it's own query string. The stream request could be either a play stream or a publish stream but we do not know which it will be or the name until the other end sends either a play or a publish request. You should be able to override the play method in your module to capture the play event at the earliest possible moment without having to use the IMediaStreamActionNotify interface. Make sure you exit the method using invokePrevious(client, function, params) so that the main play method gets called. You can do the same with publish.

    These first 2 are persistent connections. With http, there are lots of separate connections using different urls for each part. It is for this reason that it is not easy to get the full uri for the session.

    With the ip addresses, you will file that if both the client side app and Wowza are capable of ipv6 then ipv6 will be used. That is normally the case with flash player and html5 browsers. It looks like the rtsp player you are testing with doesn't do ipv6 or it is disabled.

    You can set Wowza to use ipv4 only by setting JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true" in setenv.sh or setenv.bat. This will cause Wowza to bind to ipv4 addresses only.

    Roger.

  3. #3

    Default

    Roger,
    Thank you for the thorough explanation. That is excellent support!

    Sean

  4. #4

    Default

    Hi Roger,
    I had to put this down for a few days, but now I'm back on it. I took your advice above and used the play method instead of IMediaStreamActionNotify. One problem I ran into immediately is how to get the RTMP URL parts within the play method. The IClient getUrl() method returns the connect uri, but I didn't see any way of getting the uri for the play request. I finally found it in the AMFDataList passed to that method as the "params" variable. Here's how I'm constructing the entire URL:

    String streamSourceUri = client.getUri();
    AMFData data = params.get(3);
    String filePath = data.getValue().toString();
    String requestPath = String.format("%s?%s", streamSourceUri, filePath);

    Is this correct? Is that always passed as the 4th item in the params AMFDataList collection? If so, how would I know that?

    My problem with this is that I couldn't find any of this in the documentation. I had to run the IDE in debug mode and look for the path. I finally stumbled on it after an hour or so. I hate having to do that... Am I missing something? Is there somewhere I failed to look which would have explained how to do this?

    Thanks,
    Sean

  5. #5

    Default

    Hi Sean,

    It is documented in the Server Side API documentation on this page. http://www.wowza.com/forums/content.php?188 in com.wowza.wms.module.ModuleCore. This class has the main flash to wowza interface methods that you can override. An override of the play method that shows how to get the stream name is included in these docs.

    You should also have a copy of these in your local Wowza install as a PDF and also as java docs.

    Any method that is an interface to the flash player will have the same signature. It will be
    public void someMethod(IClient client, RequestFunction function, AMFDataList params)
    params will always contain the data sent from the client that relates to the request. There are constants defined in ModuleBase for accessing the params easily, PARAM1, PARAM2 etc. PARAM1 is actually the 4th item in the list. You shouldn't need to worry about the first 3.

    AMFDataList has methods for retrieving values of common types so you can just use
    String filePath = params.getString(PARAM1);
    The methods in ModuleCore are mostly static methods. When you override them, you should use instance methods and then call
    invokePrevious(client, function, params);
    to call the same method in the next module up in the module list. ModuleCore is at the top of the list so will be called last.

    Roger.

  6. #6

    Default

    Thanks for the explanation Roger, that helps a lot. I had actually looked at the ServerSiteApi documentation, and just had missed that example, however, I had found the documentation for the play method, and it just wasn't clear how to know which param was for what. Here's what it says for play:

    public static void play(IClient client,
    com.wowza.wms.request.RequestFunction function,
    AMFDataList params)
    Server side implementation of NetStream.play(name : Object [,start : Number[, len : Number[, reset : Object]]]);
    Parameters:
    client - client
    function - function
    params - params (name, start, len, reset)

    Notice that for params it gives "(name, start, len, reset)". Shouldn't name be the last one in the list?

  7. #7

    Default

    Hi Sean,

    No, that is the correct order.

    The actual params AMFDataList has 3 other internal values that occupy positions 0 - 2 in the list. The end user data (name, start, len, reset in this case) starts at position 3. ModuleBase.PARAM1 = 3, PARAM2 = 4 etc. Depending on the method, the may be any number of params for data but they should always have the first 3 so you can be certain that PARAM1 will be the first part of usable data if it exists. The order should always be the same as for the flash method that makes the call. In this case, NetStream.play(name, start, len, reset).

    If you use getLogger().info(params.toString()); at the beginning of your method then you will see what each of the params is.

    In the case of the onConnect method, which has the same signature in Wowza, the params AMFDataList will contain any extra parameters sent from NetConnection.connect(url, extraParameters...);. It doesn't include the actual connection url

    Roger.

  8. #8

    Default

    Thanks Roger.

    Is there any way to get both parts of the URI in the disconnect method? I don't see any way of getting it since that method is only passed an IClient. To get around that, I'm doing this in my override of the play method:

    client.getProperties().setProperty("FullUri", requestPath);

    I then get the property value in the onDisconnect method. This works, but seems hacky...

    Thanks,
    Sean

  9. #9

    Default

    Hi Sean,

    Just the way you are doing it. That is what the properties is for, storing info that pertains to the client so you can retrieve it later.

    By the time disconnect is called, the stream has already been destroyed.

    Please note, with RTMP, you can have more than 1 stream per client, play can be called multiple times on a stream if there is a client side playlist. You should probably store a list of stream names in the properties and tehn iterate over these during onDisconnect. Don't store the actual stream otherwise it won't get garbage collected when destroyed until you remove it from the properties list.

    Roger.

  10. #10

    Default

    Hi Roger,
    I'm adding some logging code in the onDisconnect and onHTTPSessionDestroy events, which is my reason for needing the URI (plus a bunch of other stuff). I need to log a bunch of stuff to a webservice for analytics once the user is done watching each video. What is the best way to do that? I was talking to Richard about this in another thread. I was looking at either putting my logging code in a custom ILogNotify class, or in a module. I'd rather have it in a module, but it's harder to get at all the values I want to pass. I basically want to log the same information that gets logged to the log file when a stream is destroyed. Need a little direction on that. Is there a way, in a module, to make sure a logging event happens each time a user is done watching a given file?

    Thanks,
    Sean
    Last edited by seanngreen; 02-15-2013 at 01:54 PM.

Page 1 of 3 123 LastLast

Similar Threads

  1. Wowza module to start stream on HLS request
    By cipris in forum General Forum
    Replies: 4
    Last Post: 12-12-2014, 02:47 AM
  2. Samsung TV app: changing ordering of URL parameters for HLS requests
    By jules27 in forum Media Players and Devices Discussion
    Replies: 2
    Last Post: 06-19-2012, 05:00 PM
  3. Intercepting client requests for streams
    By michael401 in forum Server-side Modules and Code Samples Discussion
    Replies: 5
    Last Post: 02-26-2012, 08:12 AM

Posting Permissions

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