views:

75

answers:

2

I am currently working on an implementation of an application for Windows Phone 7 that should retrieve the SHOUTcast stream (inspired by this question). The stream location is represented by an IP address and a port.

Here is an example of a SHOUTcast stream URL: http://78.159.104.183:80

I am trying to make a HttpWebRequest to get the data from the stream:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://78.159.104.183:80");

Once the request is initialized, I am trying to get a response via an asynchronous callback:

request.BeginGetResponse(new AsyncCallback(GetShoutAsync), request);

GetShoutAsync looks like this:

void GetShoutAsync(IAsyncResult res)
{
     HttpWebRequest request = (HttpWebRequest)res.AsyncState;
     HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(res);
}

When I build the project and run it, it gets to the point where the request is initialized, but the callback is never called.

I noticed an interesting thing - SHOUTcast implements a technique by which when the user tries to navigate to the stream URL, the server detects the user agent and if it is a web browser, it will simply show a HTML page instead of passing application/octet-stream content.

You can still receive the stream directly if you use a slash and semicolon at the end of the stream URL: http://78.159.104.183:80/;

However, in my application, I cannot get the response - the callback seems to never be reached. I tried faking the user agent by passing it directly to the HttpWebRequest:

request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.3) Gecko/20100401 Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.9.0.2) Gecko/2008092313 Ubuntu/9.25 (jaunty) Firefox/3.8";

This works for the simple stream URL (without the semicolon at the end) to get the HTML contents, but I cannot get the binary stream.

Anyone ever encountered something like this or knows what's causing it?

A: 

It might help to switch on UseUnsafeHeaderParsing, given the flakey nature of Shoutcast "HTTP".

Does your code work when you turn it onto normal web pages?

EDIT

This looks like an excellent lead: Perhaps you need to set AllowReadStreamBuffering to false:

The AllowReadStreamBuffering property affects when the callback from BeginGetResponse method is called. When the AllowReadStreamBuffering property is true, the callback is raised once the entire stream has been downloaded into memory. When the AllowReadStreamBuffering property is false, the callback is raised as soon as the stream is available for reading which may be before all data has arrived.

The default setting for AllowReadStreamBuffering is true. This means you'll never hit the callback, because the download never ends (and left for long enough, you'll probably run out of memory). Set it to false.

spender
Yes, it works for normal web pages. On a side note, UseUnsafeHeaderParsing is not available on Windows Phone 7.
Dennis Delimarsky
No exceptions? Supposing you try the synchronous counterparts for WebRequest? Does it just hang?
spender
No exceptions at all. And no, it doesn't hang the applications - it just never executes the code inside the callback.
Dennis Delimarsky
Sorry, I meant if you do things synchronously rather than async with callback, does the code hang, throw or proceed? It might lend a clue as to where the problem lies in the async version.
spender
For Windows Phone 7 applications, you cannot download data synchronously via WebRequest or HttpWebRequest - only async calls are available.
Dennis Delimarsky
Does your code work if you execute it in a desktop (PC) ? If you can repro it on the desktop, can you take a system.net tracelog and see why the callback is not being invoked? See http://ferozedaud.blogspot.com/2009/08/tracing-with-systemnet.html on how to create the tracelog. Typically, callback should be invoked if the response was received by the app.
feroze
I see. WinPhone7 uses the Silverlight API, so no sync methods. I updated my answer with a good lead.
spender
AllowWriteStreamBuffering only applies for uploading data (by calling write on the stream returned by GetRequestStream()). It is not clear if upload is being used here.
feroze
A: 

I have no idea if this would work for you but I had the same problem,

and explicitly setting

request.AllowReadStreamBuffering = false; request.Method = "GET";

seemed to whatever reason get my callback to fire...

I'm not sure why.

Allen Ho