Thanks for all this help!

I found a solution, using the read function instead of recv() - much simpler coding this way, it's not documented well where this function comes from though. Net::HTTP is the child of several large classes...

Another confounding issue was that I suppose Net::HTTP::read_response_haders() just isn't reading the headers "right", it's somehow messing with the byte counts. So I read my own headers now. ;P

Here's a very basic solution. I hope to turn this into a subclass of Net::HTTP, or perhaps instead an instance of IO::Socket::INET and call it Net::Icecast - I'm open to suggestions. You can see also that this nugget is simply of wont for features too:

#!/usr/bin/perl -w ### Written by qbxk for perlmonks ### It is provided as is with no warranties, express or implied, of a +ny kind. Use posted code at your own risk. $|++; use warnings; use strict; use Net::HTTP; use Data::Dumper; use Carp::Assert; # use constant USER_AGENT => 'WinampMPEG/2.9'; # I got refused by som +e public servers unlessen i done it thar way use constant USER_AGENT => 'Stream-Recorder-0.01'; my %HOST = ( host => 'server.com', port => 8000, mount => '/stream' ); use constant DEBUG => 1; sub debug(@) { print STDERR "\n" . join("\n", @_) . "\n"; } sub debug_raw(@) { print STDERR @_; } sub open_connection { my %args = ( host => undef, port => 80, mount => '', user_agent => USER_AGENT, @_ ); die "Need a host name" unless defined($args{host}); $args{mount} =~ s/^\/+//g; my $sock = Net::HTTP->new(Host => $args{host}, PeerPort => $args{po +rt} ) || die $@; $sock->write_request(GET => "/$args{mount}", 'User-Agent' => $args{ +user_agent}, 'Icy-MetaData' => 1) or die $@; # my ($code, $mess, %headers) = $sock->read_response_headers( laxed + => 1 ) my ($code, $mess, %headers); while( <$sock> ) { s/\s*$//g; last if /^\s*$/; if( /^(?:HTTP\/1\.[01]|ICY) ([0-9]+) (.+)$/ ) { ($code, $mess) = ($1 +0, $2); } else { my ($h, $v) = split(/:/); $headers{$h} = $v; } } return ($sock,$code,$mess,%headers); } main: { my ($s,$code, $mess, %headers) = open_connection( %HOST ); debug "$code|$mess\n" . Dumper(\%headers); # TODO: timeout on $s. exit if( $code != 200 ); # scream and shout my ($metaint) = map { (/^icy-metaint$/i && $headers{$_}) or () } ke +ys %headers; assert( $metaint > 0 ); open OUT, '>stream-out.mp3'; binmode OUT; # very important while( 1 ) { my $buf; $s->read($buf, $metaint); print OUT $buf; my ($metadata, $metalen, $metabyte); $s->read($metabyte, 1); $metalen = unpack("C",$metabyte) * 16; if( $metalen > 0) { #We have NEW metadata! JOY $s->read($metadata, $metalen); $metadata = unpack("A$metalen", $metadata); assert( $metadata =~ /Stream/, "Not good metadata!" ); #don't + dump a lot of BS (binary *#$!), just die. debug "$metalen - [$metadata]"; } else { $metadata = ''; debug_raw "-"; } } }
You'll find a clean, "un-meta"ed mp3 file ever growing, called "stream-out.mp3" in your working directory... i've done enough for one night so that's how it stays.

It's not what you look like, when you're doin' what you’re doin'.
It's what you’re doin' when you’re doin' what you look like you’re doin'!
     - Charles Wright & the Watts 103rd Street Rhythm Band

In reply to Re: Reading (and parsing) a byte stream by qbxk
in thread Reading (and parsing) a byte stream by qbxk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.