title: rtsp over http over a proxy
body: <p>I am trying to fetch an RTSP stream over HTTP using a proxy. The behavior of the Real client seems to be a bit hectic: it tries all the possible ports, methods and protocols at once. The only thing that should work is HTTP GET over port 80. Such a request is indeed issued, and is received on the server. Here's how the request looks when it is sent by the proxy to the server:</p>
  
  <pre><code>GET /SmpDsBhgRl83c52ef2-d0f4-41ac-bada-93e5350f67d1?1="1" HTTP/1.0\r\n
  Connection: Keep-Alive\r\n
  Host: 10.194.5.162:80\r\n
  Pragma: no-cache\r\n
  User-Agent: RealPlayer G2\r\n
  Expires: Mon, 18 May 1974 00:00:00 GMT\r\n
  Accept: application/x-rtsp-tunnelled, */*\r\n
  ClientID: WinNT_5.1_6.0.14.806_RealPlayer_R41UKD_en-GB_686\r\n
  X-Actual-URL: rtsp://10.194.5.162:554/01.mp3\r\n
  \r\n
  </code></pre>
  
  <p>Here's the server's response:</p>
  
  <pre><code>HTTP/1.0 200 OK\r\n
  Server: RMServer 1.0\r\n
  Expires: Mon, 18 May 1974 00:00:00 GMT\r\n
  Pragma: no-cache\r\n
  x-server-ipaddress: 10.194.5.162\r\n
  Content-type: audio/x-pn-realaudio\r\n
  \r\n
  </code></pre>
  
  <p>At this point 4 more bytes arrive from the server (their values are 48 02 02 00) - and that's it, nothing more. Does the server expect anything from the client at this point, and if so - what? Does this mode of operation work at all?</p>
  
  <p>Some more info on this problem: apparently, the intended mechanism of working with RTSP over HTTP built into RealPlayer is as follows:</p>
  
  <ol>
  <li>Try to connect to the following ports: 80, 8080, 554, 7070.
  (Try also to download the file directly, just for the heck of it, by issuing GET <a href="http://hostname:port/mediafilename" rel="nofollow noreferrer">http://hostname:port/mediafilename</a> on port 80)</li>
  <li>For each of the above ports, create 2 connections. </li>
  <li>Send a GET request to one of the connections to the url <a href="http://hostname:port/SmpDsBhgRl" rel="nofollow noreferrer">http://hostname:port/SmpDsBhgRl</a><code>&lt;guid&gt;</code>?1="1", where <code>&lt;guid&gt;</code> is, yes, a freshly created GUID. Add a header to this request called X-Actual-URL containing the original RTSP URL.</li>
  <li>Send a POST request on the other connection, to the URL <a href="http://hostname:port/SmpDsBhgRl" rel="nofollow noreferrer">http://hostname:port/SmpDsBhgRl</a> with the GUID above as part of the body of the request. Send a Content-Length header of 32767 bytes, to prevent the proxy from closing the connection prematurely.</li>
  <li>Start issuing commands to the server through the POST request, and get the corresponding RTSP stream as part of the GET response.</li>
  </ol>
  
  <p>The strange stuff (if the above isn't strange enough) is that, for example, it works with Squid, but not if you use either of the ports 3128 or 8080! Somehow, the client uses the port it connects to to decide on the order of the requests or on when a request should be canceled, but anyway, as hard to believe as it is, it works with proxy port 9090, 3129, 8081, but not with 3128 or 8080.</p>
  
  <p>Update #2: <a href="https://helixcommunity.org/viewcvs/protocol/common/util/hxcloakedsocket.cpp?view=markup" rel="nofollow noreferrer">Here</a>'s the source of the RealPlayer with the explanation of the above behavior. Still no solution though.</p>
  
  <p>Update #3: OK, in the light of the above, the magic value of 48 02 02 00 is clear: 48 == 'h' is for <code>HTTP_RESPONSE</code>, the next 02 is the length of the following data, the next 02 is called <code>POST_NOT_RECEIVED</code> (meaning that the POST request did not reach the server within a second from the corresponding GET request).</p>
  
  <p>Update #4: This behavior (i.e. POST requests with huge Content-Length) is also characteristic of an ActiveX used by WebEx (and, possibly, many other web apps that need an open channel to the server).</p>