IOS troubles with binary data on windows

B

brandon

I'm at a loss.

Writing data from a file to an IOS blows up on windows. You get '
Invalid argument (Errno::EINVAL)'.

The code is below. @ezstream is an IOS opened r+b. If I read the files
with http it works. As in http_req_result.read_body { |segment|
@ezstream.write segment}.....this works.

Any suggestions? It's really strange.

Here is the code:

f = File.open(track_info['file_path'],'rb')
chunk = ''

until chunk.nil?
chunk = f.read(16000,'rb')
unless chunk.nil?
@ezstream.write chunk #blows up here
end
end
 
B

brandon

I just found an error in my code, but it wasn't causing a problem

this:

chunk = f.read(16000,'rb')

should be:

chunk = f.read(16000)

I also jumped the gun a little. It doesn't look like it's a binary data
problem. It looks like you can't stream from a file to a IO.popen
stream. I'm not sure if I'm right though.

The funny thing is I can @ezstream.write 'any old string' and it works.
writing a chunk from a file, which always gets converted to a string,
does not.
 
B

brandon

Ok....I confirmed this a few different ways. It may be a new bug.

On windows, you can't send binary data from a file over to another
system pipe. It blows up. It will work from a network socket to a system
pipe, and it will work from a local text file to a system pipe, but not
from a binary file to a system pipe.
 
S

shortcutter

2007/11/2 said:
Ok....I confirmed this a few different ways. It may be a new bug.

On windows, you can't send binary data from a file over to another
system pipe. It blows up. It will work from a network socket to a system
pipe, and it will work from a local text file to a system pipe, but not
from a binary file to a system pipe.

Few remarks: if you post code then you should people give at least the
chance to understand what's going on. In your first posting it was
not clear from the code shown what @ezstream is.

Note that there is no #read method which will accept a binary flag.
Instead the portion read is put into the string provided. In your
case this leads to unnecessary string creations that get overwritten
immediately ('rb' will create a new string each time it is executed).

Then, did you consider decreasing the buffer size? 16,000 seems quite
high. I'd start with 1,024.

Also, the looping can be done more elegantly:

while ( chunk = r.read(1024) )
...
end

If you want to be even more savvy you can do

chunk = ""
while r.read(1024, chunk)
...
end

Cheers

robert
 
B

brandon

The chunk size isn't the problem.

This code streams mp3 data to standard input for a pipe opened up an an
executable called ezstream. Ezstream is a source for icecast server.


here is @ezstream:

@ezstream = IO.popen("C:\\Program
Files\\ezstream-0.4.3-win32\\ezstream.exe -c \"C:\\Program
Files\\ezstream-0.4.3-win32\\examples\\stdin.xml\"", "r+b")

This code works on Windows:

url = get_track_url

Net::HTTP.start(url.host, url.port) do |http|
http.request_get(url.request_uri, {"User-Agent"=>"Mozilla/5.0
(Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010
Firefox/2.0"}) do |res|
raise "Bad response :#{res.code}: #{res.body}" unless res.code ==
"200"
res.read_body do |segment|
@ezstream.write segment
end
end
end


This code does not work on Windows:

f = File.open(get_file_path,'rb')
count = nil
until count == 0
count = @ezstream.write(f.read(1024))
#Invalid argument (Errno::EINVAL)
# you get a broken pipe exception with sysread and syswrite too
end

Any ideas what is so different about chunking a file from disk versus
chunking the file from an http network stream?
 
S

shortcutter

2007/11/2 said:
The chunk size isn't the problem.

This code streams mp3 data to standard input for a pipe opened up an an
executable called ezstream. Ezstream is a source for icecast server.


here is @ezstream:

@ezstream = IO.popen("C:\\Program
Files\\ezstream-0.4.3-win32\\ezstream.exe -c \"C:\\Program
Files\\ezstream-0.4.3-win32\\examples\\stdin.xml\"", "r+b")

This code works on Windows:

url = get_track_url

Net::HTTP.start(url.host, url.port) do |http|
http.request_get(url.request_uri, {"User-Agent"=>"Mozilla/5.0
(Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010
Firefox/2.0"}) do |res|
raise "Bad response :#{res.code}: #{res.body}" unless res.code ==
"200"
res.read_body do |segment|
@ezstream.write segment
end
end
end


This code does not work on Windows:

f = File.open(get_file_path,'rb')
count = nil
until count == 0
count = @ezstream.write(f.read(1024))
#Invalid argument (Errno::EINVAL)
# you get a broken pipe exception with sysread and syswrite too
end

Any ideas what is so different about chunking a file from disk versus
chunking the file from an http network stream?

Check the documentation, especially the return value of #write. Note
also the copying algorithm I suggested. Hint: your file copying is
flawed.

Cheers

robert
 
B

brandon

It still fails with your your file copying code. Though last night I
didn't notice, it does write a little bit of data to the pipe , then
ezstream closes. From ezstream's output it looks like it can't process
the data sent from a file to the pipe, it blurts out socket error. It
likes the data from an http stream though, and it's likes the data when
it's not fed through standard input. You can give ezstream a list of
tracks in it's own config file too.

By the way, the same method works with .Net code. I was able to feed
ezstream data to standard input with some .Net code and that works.

I've done a lot of work on Windows with Ruby and I'm getting tired of
all the idiosyncrasies that pop up between linux and windows. I'm just
going to switch to a linux work station. All my code gets deployed to
linux anyway.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top