We have shoutcast/icecast audio streams. I'd like to be able to provide a link such as mobiledroid.php on our web site that will open using default player. I've seen this done on another site so I do know it's possible.
I assume it uses php headers and streams via the php file as a stream?
Using Brad's instructions, the android actually gives the option to open with sound player. Nice one.
It also plays on WMP through PC but not on the android how the above link plays
header("Content-type: audio/mpeg");
header("Transfer-Encoding: chunked");
header("Connection: close");
$sock = fsockopen($streamname,$port); //$streamname is the IP
fputs($sock, "GET $path HTTP/1.0\r\n"); //path in my case is /;stream.mp3
fputs($sock, "Host: $ip\r\n");
fputs($sock, "User-Agent: WinampMPEG/2.8\r\n");
fputs($sock, "Accept: */*\r\n");
fputs($sock, "Icy-MetaData:1\r\n");
fputs($sock, "Connection: close\r\n\r\n");
fpassthru($sock);
fclose($sock);
On the android, it says "Sorry, this player does not support this type of audio file"
Update 2:
Removing "Transfer-Encoding" will play on android but as usual will take a long time to begin stream with "Preparing" status due to a live stream not having "Content-Length"
header("Transfer-Encoding: none"); also removed from above code:
Quoting Brad:
Android 2.3 and later has an issue with Transfer-Encoding set to "none". Removing that hard-set header puts the stream back to chunked Transfer-Encoding. This works great for Android 2.3+. Originally I had disabled chunked encoding as VLC doesn't support it. It also seems that Android 2.2 and older does not support chunked encoding.
Noting here that although it works on android, most live streams will take an awful amount of time to begin.
Problem
Traditionally, you would serve a playlist file which would be saved by your browser, and then opened in whatever player software was configured to open such playlists. The player would then read the URL of the stream, connect to it, and begin streaming.
On Android, they (for some crazy reason) chose not to support playlist files as supported media. Because of this, there is no direct way to launch the player using the traditional method.
Solution
On Android it seems that if you link directly to an MP3 file/stream, instead of downloading the file the default action is to open up a media player and try to stream it. This means that you can easily link directly to the URL of your stream (bypassing the playlist step entirely).
There is a catch... streams served with SHOUTcast aren't exactly HTTP compliant. They are close, but not perfect. The real hangup here seems to be one of content length. Typically, HTTP servers send a Content-Length response header. With streaming media, the length is unknown. There are two ways around the problem:
Use chunked transfer encoding. You can do this by setting the following headers: Transfer-Encoding: chunked Then, use chunked encoding for the stream, and you're good to go.
Use no transfer encoding, and specify that the connection will be closed when the resource is finished transferring, with these headers: Transfer-Encoding: none Connection: close
Your example link uses method one. I'm using method two successfully as well.
Once your server is talking valid HTTP, playback on Android seems to be a breeze.
Implementation
There are a handful of ways to go about implementing this fix. You have mentioned a PHP solution. If cURL won't work, you can always fsockopen() or stream_socket_client() to make a direct TCP connection, and handle the incoming stream data yourself. From there, you simply need to send the correct response headers and relay the data as it comes in. Keep in mind that a PHP instance will be running for each connected client, and each instance will make a connection to your server as well. This isn't ideal, but depending on what you have available, might be the only method for you.
Related
we're using a custom built cart system and during high loads our payment system (Worldpay) times out.
When this happen we receive an email containing the POST request that failed, and this is a .txt file done like the following:
POST /index.php?xxx=yyy&zzz=xxx HTTP/1.0
Content-Length: 917
Host: ourdomain.com
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
User-Agent: WJHRO/1.0 (WorldPay Java HTTP Request Object)
parameter1=value¶meter2=value2
How can I actually quickly resend this request to my server so it can register the payment now that the load is more normal? I have this in a .txt file, is there a quick way to do it using this file as it is? Curl? Browsers? In a way so I can see the response to check that all is ok.
Thanks so much!
Depending on the needs you have exposed, it is likely that tools such as POSTMAN could help you, allow you to send http requests through an intuitive interface, you can use the various parameters, that are sent to you in the file you mentioned and run the same request check for any errors.
The topic is a bit strange, let me express myself.
I used this method to generate post requests:
http://www.jonasjohn.de/snippets/php/post-request.htm
thats ok, but after a size, I realized the datas gets changes a little, there are unwanted white spaces. Only in case of a bigger size, + a "chunked" flag appeared.
I change the Http/1.1 protocol to Http/1.0 and now the transfers look good!
But is there any backward, pitfalls?
Well there are a number of important differences between http 1.0 and 1.1 of course, look at this article for an overview.
One that I can directly spot as affecting your code is
// send the request headers:
fputs($fp, "POST $path HTTP/1.1\r\n");
fputs($fp, "Host: $host\r\n");
The Host header field doesn't exist in http 1.0, and that could affect your ability to post to servers that host multiple domains and/or subdomains via name based virtual hosting - the server won't know what domain you're calling.
As a general note, writing a post request this way is a nice exercise and it's always good to know what goes on under the hood, but for production purposes I'd use a full-blown, well tested mechanism like cURL
And for reference:
rfc 1945 defines http 1.0
rfc 2616 defines http 1.1
I have an app which connects to my web server and transfers data via XML.
The headers I connect with are:
POST /app/API/Data/Receiver.php HTTP/1.1
User-Agent: Custom User Agent 1.0.0
Accept: text/xml
Content-Type: text/xml
Content-Length: 1580
Host: servername.com
The app then handles the data and returns its own XML formatted reply. One of the header's I'm setting in the response is:
header("Connection: close");
When I send connect and send my data from a simple app on my PC (C++) it works fine, I get the close header correctly and the connection is closed as soon as the data is available. When I send the exact same data using a GSM modem and and embedded app, the connection header comes back as:
header("Connection: keep-alive");
The GSM modem also sits and waits until the connection is closed before moving on and often just times out.
Is there someway to close the connection on the server so that the GSM side does not time out?
It is possible that your GSM service provider transparently proxing connections. Try to send data on non-standard port (i.e not 80, 8080, 443)
Also setting cache control header private might work.
Cache-Control: PRIVATE
Headers are just plain text but cannot be sent once data has been sent in PHP. Try this:
echo "\r\n\r\nConnection: close";
die();
and adjust to your needs
I'm using the stats plugin for wordpress which uses a core wordpress class IXR_Client in class-IXR. Although according to documentation it uses the proxy config found in wp-config.php I see no way it can as it uses the same address for host as it does in fsockopen (looking at fsockopen it should be the proxy address)
I've modified the fsockopen to point to my proxy and it does receive a response now from the proxy although 'TCP_DENIED/400 4139 POST error:invalid-request - NONE/- text/html' comes up in the proxy logs and the proxy returns an error. I have a feeling I'm not wrapping the request right for the proxy.
The request: (some things changed)
POST /xmlrpc.php HTTP/1.0 Host: wordpress.com Content-Type:
text/xml User-Agent: The Incutio XML-RPC PHP Library Content-Length: 1770 <?xml
version="1.0"?> <methodCall> <methodName>wpStats.check_key</methodName> <params>
<param><value><string>123456789012</string></value></param> <param><value><struct>
<member><name>host</name><value><string>thedomainoftheblog.com</string></value></member>
<member><name>path</name><value><string>/</string></value></member>
<member><name>admin_bar</name><value><string>1</string></value></member>
<member><name>wp_me</name><value><string>1</string></value></member>
<member><name>reg_users</name><value><string></string></value></member>
<member><name>footer</name><value><string>1</string></value></member>
<member><name>version</name><value><string>7</string></value></member>
<member><name>error</name><value><string></string></value></member>
<member><name>blogname</name><value><string>THE | BLOG NAMEFUL</string></value></member>
<member><name>blogdescription</name><value><string>blogs name norma
l</string></value></member><member><name>siteurl</name>
<value><string>http://thedomainoftheblog.com</string></value></member>
<member><name>gmt_offset</name><value><string>0</string></value></member>
<member><name>timezone_string</name><value><string></string></value></member>
<member><name>stats_version</name><value><string>7</string></value></member>
<member><name>stats_api</name><value><string>jetpack</string></value></member>
<member><name>page_on_front</name><value><string>0</string></value></member>
<member><name>permalink_structure</name><value>
<string>/%year%/%monthnum%/%day%/%postname%/</string></value></member>
<member><name>category_base</name><value><string></string></value></member>
<member><name>tag_base</name><value><string></string></value></member> </struct></value></param> </params></methodCall>
If you need more information let me know.
Cheers
The trick seems to be to add http://your.domain.name/ on the POST request (i.e. not only POST/name-of-file, as class-IXR.php has by default), at least according to the following link: http://thedeadone.net/how-to/livejournal-and-wordpress/
I've tried it out and it certainly works.
There are a few proxy-related constants in WP, as well as a whole bunch of other constants used in wp-includes/class-http.php. Have you tried to set any or all of them? e.g.:
WP_PROXY_HOST
WP_PROXY_PORT
WP_PROXY_USERNAME
WP_PROXY_PASSWORD
WP_PROXY_BYPASS_HOSTS
While most of the time I'd just use file_get_contents and CURL, I can't get it to work with a port in the URL. How can I read this file?
http://174.120.124.178:7800/7.html (It's a shoutcast statistics file)
Ultimately, I just want the text after the last comma.
It has nothing to do with the port. They're blocking you because you're not using a browser user agent. curl does let you fake the user agent, but that may be a violation of the site's terms of service.
According to this post it's not about blocking scripts, but just distinguishing between Shoutcast clients and everything else. So the code is:
curl_setopt($curl_handle, CURLOPT_USERAGENT, "Mozilla");
I tried to download your file with Curl on the command line and got a 404 error; it does load with Firefox and Lynx. This page says that you need to change the User-Agent string for it to download.
CURLOPT_PORT Needs to be set to the appropriate port perhaps~