Forum Discussion
albert_forster_
Nimbostratus
Feb 02, 2005persistence with rtsp
we are trying to enable persistence based on a universal persistence profile using an irule for rtsp connections.
we have multiple helix servers installed and when accessing video streams via the real player we want connections to persist to one of the helix servers as long as the chanel-set-id specified in the rtsp uri stays the same.
in the real player we are using for instance this uri:
rtsp://158.226.219.222:554/africag2/giraffe-2sm.jpg?CHSETID=45&xyz=martin
... and the irule we defined looks like this:
when HTTP_REQUEST {
set rtsp_chsid [findstr [HTTP::query] "CHSETID=" 0 "&"]
set rtsp_uri [HTTP::uri]
log "Found ChanelSetID $rtsp_chsid in request!!!"
log "Found RTSP uri from query = $rtsp_uri"
findstr [HTTP::query] "CHSETID=" 0 "&"
}
the log entries show, that the irule sometimes finds the chanel-set-id in the rtsp-request, but that there are also rtsp-requests belonging to this session, which do not include the chanel-set-id:
die durch diese irule erzeugten log-einträge:
ltm:Feb 1 17:27:46 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found ChanelSetID in request!!!
ltm:Feb 1 17:27:47 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found RTSP uri from query = /SmpDsBhgRl
ltm:Feb 1 17:27:47 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found ChanelSetID CHSETID=45 in request!!!
ltm:Feb 1 17:27:47 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found RTSP uri from query = /SmpDsBhgRlce6cdda9-8a50-4c26-a2f3-83b059a0fcde
ltm:Feb 1 17:28:06 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found ChanelSetID in request!!!
ltm:Feb 1 17:28:06 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found RTSP uri from query = rtsp://158.226.219.222:554
ltm:Feb 1 17:31:04 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found ChanelSetID in request!!!
ltm:Feb 1 17:31:04 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found RTSP uri from query = rtsp://158.226.219.222:554
ltm:Feb 1 17:31:24 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found ChanelSetID in request!!!
ltm:Feb 1 17:31:24 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found RTSP uri from query = /SmpDsBhgRl
ltm:Feb 1 17:31:24 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found ChanelSetID CHSETID=45 in request!!!
ltm:Feb 1 17:31:24 tmm tmm[357]: 01220002:6: Rule _rtsp_persist_on_chanel_set_id : Found RTSP uri from query = /SmpDsBhgRl1ff70c47-f05c-4c83-b73f-fd914257b080
... therefore requests from this single rtsp session are distributed to multiple helix servers (as seen in the pool statistics), and the real player fails to play the video stream.
so finally our question is: is this kind of rtsp-session-persistence possible with irules and how can it be configured?
additional info: we traced the rtsp stream on the helix server with and without the loadbalancer and the rtsp packages seem to be modified by the loadbalancer (no rtsp methods are visible and the video stream file which should be played is not contained in the rtsp uri, but in an rtsp continuation package).
is there any possibility to disable this modification of the rtsp packages by the loadbalancer?
kind regards,
albert
4 Replies
- Mark_Crosland_1Historic F5 AccountReal-Networks can tunnel RTSP through HTTP. They use the URI /SmpDsBhgRl to
do so. There are two scenarios.
1) There is one POST and one GET.
2) There are multiple POSTs and one GET.
The player will do one or the other based on whether a timely response is
received to the first POST. The following rule will work in either case.
If you want to load balance based on the URI in the RTSP URI you need to
force the second scenario. In the first scenario they send a bogus
content length, 32767, and trying to HTTP::collect it all will cause
enough of a delay (really imperceptible to the user) to force the second
scenario where each POST contains a content length that matches what
they send. The 32767 content-length isn't really bogus, it is just that
they never actually send that much data.
The HTTP POST commands are used by the client to send base64 encoded RTSP
commands. That is why you don't see the RTSP methods, they have been
encoded.
The single HTTP GET command is used as a virtual channel to stream the
audio/video back to the client.
The first 36 bytes of content in each POST contain a session identifier. If
you see /SmpDsBhgRl in a POST URI, collect the 36 bytes of data. When the
36 bytes of data arrives the HTTP_REQUEST_DATA event is fired. Use
HTTP::payload to get the session ID and then persist it.
The rule below will also decode the tunnelled RTSP requests and find the
URI in the DESCRIBE request (typically the first request that contains
a URI). You can then use the uri variable to make further load balancing
decisions.when HTTP_REQUEST { set decode_rtsp 0 if { [HTTP::method] eq "POST" && [HTTP::uri] eq "/SmpDsBhgRl" } { if { [HTTP::header exists "Content-Length"] } { set clen [HTTP::header value "Content-Length"] if { $clen == 32767 } { force multi-post mode, 32767 bytes are never sent HTTP::collect $clen or just collect the session ID, however, the player may choose to go into multi-post mode anyway HTTP::collect 36 } else { set decode_rtsp 1 HTTP::collect $clen } } } elseif { [HTTP::method] eq "GET" } { set uri [HTTP::uri] if { [string compare -length 11 "/SmpDsBhgRl" $uri] == 0 } { set session_id [string range $uri 11 end] persist universal $session_id } } } when HTTP_REQUEST_DATA { set content [HTTP::payload] set session_id [string range $content 0 35] set decode_idx [expr $clen - 2] persist universal $session_id if { $decode_rtsp } { set rtsp_request [b64decode [string range $content 38 $decode_idx]] if { [string compare -length 8 $rtsp_request "DESCRIBE"] == 0 } { set end_of_uri [string first " RTSP/1.0" $rtsp_request] set uri [string range $rtsp_request 9 $end_of_uri] now you can dig into the "real" URI to load balance to specific nodes based on the presentation or to persist } set decode_rtsp 0 } HTTP::release } - albert_forster_
Nimbostratus
hello,
thank you for your reply. but we are trying to force all components to use pure rtsp - we don't want to handle rtsp-tunneling via the loadbalancer.
so we configured the real player not to use http-tunneling and traced on the client node and on the helix-server node with ethereal.
when we start a streaming download of a *.wmv-file, then we can access the stream and we see rtsp tunneled via http sent to the rtsp-port.
but when we start a streaming download of a *.rm-file, then the real player tries to use pure rtsp. in this case the rtsp-options request is received on the helix-server-node, but we can NOT see the following rtsp-describe request sent by the client on the helix-server node, although the client receives an answer to this request (and the stream can not be downloaded).
so we think that the answer must be produced by the loadbalancer itself (see the attached ethereal-traces).
is this observed behaviour part of the loadbalancer configuration (if that's the case: how can we disable this?)
can the real player be forced to always use pure rtsp (not tunneled in any way)? and is there a difference in the protocol choosen by the real player dependent on the streamed media type (rm, wmv, ...)?
thanks,
albert
=======================================================================
this is an ethereal trace taken on the client-side, where
we tried to download a media stream (*.rm) via pure rtsp, but failed
because the rtsp-describe never reached the helix-server (and we
think the loadbalancer answered instead of the helix-server).
=======================================================================
OPTIONS rtsp://158.226.219.222:554 RTSP/1.0
CSeq: 1
User-Agent: RealMedia Player (HelixDNAClient)/10.0.0.0 (win32)
ClientChallenge: 1f86e2c643592f625a33fda9efa4fec3
ClientID: WinNT_5.1_6.0.12.1056_RealPlayer_R30DED_de-at_686
CompanyID: /0xfnpVYGBwuXMQwGzpM+g==
GUID: 00000000-0000-0000-0000-000000000000
PlayerStarttime: [04/02/2005:14:38:11 01:00]
Pragma: initiate-session
RegionData: 1140
RTSP/1.0 200 OK
CSeq: 1
Date: Fri, 04 Feb 2005 13:45:51 GMT
Session: 23478-1
Server: Helix Server Version 9.0.5.1159 (sunos-5.8-sparc-server) (RealServer compatible)
Public: OPTIONS, DESCRIBE, ANNOUNCE, PLAY, SETUP, GET_PARAMETER, SET_PARAMETER, TEARDOWN
RealChallenge1: 743343e19df49991f747138ef6b10f4e
StatsMask: 3
DESCRIBE rtsp://158.226.219.222:554/real9video.rm?CHSETID=41&xyz=martin RTSP/1.0
CSeq: 2
User-Agent: RealMedia Player (HelixDNAClient)/10.0.0.0 (win32)
Accept: application/sdp
Session: 23478-1
Bandwidth: 1544000
ClientID: WinNT_5.1_6.0.12.1056_RealPlayer_R30DED_de-at_686
Cookie: cbid=rfqgjhcidjfkhldmeoloqphqerjrktlufkrgkieliggkilplmsnrqugqlorndtdudfjjdhci
GUID: 00000000-0000-0000-0000-000000000000
Language: de-at
RegionData: 1140
Require: com.real.retain-entity-for-setup
SupportsMaximumASMBandwidth: 1
=======================================================================
this is an ethereal trace taken on the client-side, where
we tried to download a media stream (*.wmv) via pure rtsp, but we
saw a rtsp request tunneled via http and sent to the rtsp port:
(and we could access the data stream)
=======================================================================
GET /wmvideo.wmv?CHSETID=36&xyz=mp HTTP/1.1
Accept: */*
User-Agent: NSPlayer/9.0.0.2980
Host: 158.226.219.222
Cookie: cbid=rfqgjhcidjfkhldmeoloqphqerjrktlufkrgkieliggkilplmsnrqugqlorndtdudfjjdhci
X-Accept-Authentication: Negotiate, NTLM, Digest, Basic
Pragma: version11-enabled=1
Pragma: no-cache,rate=1.000,stream-time=0,stream-offset=0:0,packet-num=4294967295,max-duration=0
Pragma: packet-pair-experiment=1
Pragma: pipeline-experiment=1
Supported: com.microsoft.wm.srvppair, com.microsoft.wm.sswitch, com.microsoft.wm.predstrm
Pragma: xClientGUID={3300AD50-2C39-46c0-AE0A-CC44945DC0BE}
Accept-Language: de-DE, *;q=0.1
HTTP/1.0 200 OK
Content-Type: application/octet-stream
Server: Cougar 4.1.0.3917
Cache-Control: no-cache
Pragma: no-cache
Pragma: client-id="5483"
Pragma: features="seekable,stridable"
$H.....<----- snip ----> - Mark_Crosland_1Historic F5 AccountIdeally you would like the transport to be UDP based. The client advertises one or more ports to the server and the server selects its own port set. The RTSP control channel remains for the duration of the presentation, but the audio/video is streamed over UDP using the ports selected by the client and server. Port holes need to be opened in the BigIP for this to work. Depending on where you clients are you may encounter firewall issues with this configuration. The BigIP does not currently support this. Native support for RTSP was completed recently but has not been released yet.
The next best option is to have the audio/video sent over the RTSP control connection. This is similar to HTTP tunneling but with less overhead. The audio/video is sent in binary form, no base64 encode/decode step involved and there are no HTTP headers to deal with. You can force this in real player by selecting the TCP option (and un-selecting the other transports) in the manual RTSP settings under tools>preferences>network transport.
The TCP option works with a simple virtual such as the following.
virtual helix {
destination 10.1.30.2:rtsp
ip protocol tcp
profile fastL4
pool helix
}
Hope this helps. - marlon_Gino-gi1
Nimbostratus
thanks for the info
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects