Blocking read after select

Hi,

I've some trouble reading an IO after a select

Here is the code.

while sock = tunnel.accept

  Thread.start(sock) do |s|

    ssl_sock = get_ssl_socket("ssl.gwikzone.org", 443)

    #set_non_blocking ssl_sock.to_io
    #set_non_blocking s.to_io
    STDERR.puts "thread start
#{Thread.current.object_id}/#{s.object_id}/#{ssl_sock.object_id}"

    while true
      STDERR.puts "select..."
      res = select([s, ssl_sock])

      unless res.nil?

        for rsock in res[0]
          #delete closed connections
          if rsock.eof? || ssl_sock.closed?
            s.close
            ssl_sock.close
            Thread.current.terminate
          end

          if rsock == s
            STDERR.puts "read s"
            buf = s.read
            STDERR.puts "s: \n#{send}"
            ssl_sock.write buf unless buf.nil? || buf.empty?
          end

          if rsock == ssl_sock
            STDERR.puts "read ssl"
            buf = rsock.read
            STDERR.puts "ssl: \n#{send}"
            s.write buf unless buf.nil? || buf.empty?
          end

        end #for
      end #unless
    end #while true
  end #Thread.start

end #while

output :

thread start 539408208/539408228/539408078
select...
read s
<<--- get stuck here

I tried to use non-blocking io but same thing happened which is very
strange.

Thank's for help

···

--
Posted via http://www.ruby-forum.com/.

Antonin AMAND wrote:

Hi,

I've some trouble reading an IO after a select

Could it by related with the fact that require use openssl stdlib

···

--
Posted via http://www.ruby-forum.com/\.

you are calling IO#read, which reads till eof. try something like

   buf = rsock.read 8192

and you should see data. typically one would have the client do somthing like

   bufsize = [buf.size].pack 'N'
   s.write bufsize
   s.write buf
   s.flush

and, in the server, something like

   bufsize = s.read 4
   bufsize = bufsize.unpack('N').first
   buf = s.read bufsize

in otherwords, every message is preceded by it's length in a packet guarunteed
to be 4 bytes big. you might start out with something like this (untested):

   class NetString < ::String
     def self.recv io
       buf = io.read 4
       size = buf.unpack('N').first
       new(read(size))
     end

     def self.send s, io
       s = s.to_s
       size = [s.size].pack('N')
       io.write size
       io.write s
     end

     def send io
       self.class.send self, io
     end
   end

then you can do

   ns = NetString.recv socket

or

   ns = NetString.new 'foobar'
   ns.send socket

regards.

-a

···

On Mon, 26 Jun 2006, Antonin AMAND wrote:

Hi,

I've some trouble reading an IO after a select

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

unknown wrote:

···

On Mon, 26 Jun 2006, Antonin AMAND wrote:

Hi,

I've some trouble reading an IO after a select

you are calling IO#read, which reads till eof. try something like

   buf = rsock.read 8192

I've already tried that with different values. I also tried with IO#gets
(with different values as separator("\n", "\r\n", "\n")). It always
block.

I've used tcpdump to see if something comming on the socket and it does,
but i'm never able to read. That's very very strange.

Does the fact that I require 'openssl' modify the problem.

--
Posted via http://www.ruby-forum.com/\.

Here is the full code.

The goal is to provide a https tunnel. In order to use iCal with ssl
socket.
The server will listen on 127.0.0.7:8888 and forward all traffic comming
from one socket to a ssl socket connected to the distant https server.
And back.

#! /usr/bin/env/ruby

require 'openssl'
require 'socket'

def set_non_blocking(io)
  flag = File::NONBLOCK
  if defined?(Fcntl::F_GETFL)
    flag |= io.fcntl(Fcntl::F_GETFL)
  end
  io.fcntl(Fcntl::F_SETFL, flag)
end

def get_ssl_socket(host, port)
  ssl_context = OpenSSL::SSL::SSLContext.new()
  ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
  socket = TCPSocket.new(host, port)
  sslsocket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
  unless ssl_context.verify_mode
    warn "warning: peer certificate won't be verified this session."
  end
  sslsocket.sync_close = true
  sslsocket.connect
  sslsocket
end

## FIXME: listen on all interfaces -> localhost
tunnel = TCPServer.new(8888)
tunnel.listen(5)

while sock = tunnel.accept

  Thread.start(sock) do |s|

    ssl_sock = get_ssl_socket("ssl.gwikzone.org", 443)

    #set_non_blocking ssl_sock.to_io
    #set_non_blocking s.to_io
    STDERR.puts "thread start
#{Thread.current.object_id}/#{s.object_id}/#{ssl_sock.object_id}"

    while true
      STDERR.puts "select..."
      res = select([s, ssl_sock])

      unless res.nil?

        for rsock in res[0]
          #delete closed connections
          if rsock.eof? || ssl_sock.closed?
            s.close
            ssl_sock.close
            Thread.current.terminate
          end

          if rsock == s
            STDERR.puts "read s"
            buf = s.read unless s.ready?
            STDERR.puts "s: \n#{send}"
            ssl_sock.write buf unless buf.nil? || buf.empty?
          end

          if rsock == ssl_sock
            STDERR.puts "read ssl"
            buf = rsock.read
            STDERR.puts "ssl: \n#{send}"
            s.write buf unless buf.nil? || buf.empty?
          end

        end #for
      end #unless
    end #while true
  end #Thread.start

end #while

···

--
Posted via http://www.ruby-forum.com/.

The goal is to provide a https tunnel. In order to use iCal with ssl

socket.
<<<

Try the eventmachine library. Can probably accomplish this goal with much
less code.

if you make the mod i suggested it works fine:

harp:~ > ruby a.rb
thread start -609397948/-609397928/-609398078
select...
reading s...
read: <"11223 @ Mon Jun 26 08:18:09 MDT 2006\n">
select...
thread start -609398348/-609398318/-609398498
select...
reading s...
read: <"11224 @ Mon Jun 26 08:18:10 MDT 2006\n">
select...
thread start -609398768/-609398738/-609398918
select...
reading s...
read: <"11225 @ Mon Jun 26 08:18:11 MDT 2006\n">
select...

harp:~ > cat a.rb
#! /usr/bin/env/ruby

require 'openssl'
require 'socket'

def set_non_blocking(io)
   flag = File::NONBLOCK
   if defined?(Fcntl::F_GETFL)
     flag |= io.fcntl(Fcntl::F_GETFL)
   end
   io.fcntl(Fcntl::F_SETFL, flag)
end

def get_ssl_socket(host, port)
   ssl_context = OpenSSL::SSL::SSLContext.new()
   ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
   socket = TCPSocket.new(host, port)
   sslsocket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
   unless ssl_context.verify_mode
     warn "warning: peer certificate won't be verified this session."
   end
   sslsocket.sync_close = true
   sslsocket.connect
   sslsocket
end

## FIXME: listen on all interfaces -> localhost
tunnel = TCPServer.new(8888)
tunnel.listen(5)

## fork tester clients in background
fork do
   loop do
     fork do
       s = TCPSocket.new 'localhost', 8888
       s.puts "#{ $$ } @ #{ Time.now.to_s }"
     end
     Process.wait
     sleep 1
   end
end

while sock = tunnel.accept

   Thread.start(sock) do |s|

     ssl_sock = get_ssl_socket("ssl.gwikzone.org", 443)

     #set_non_blocking ssl_sock.to_io
     #set_non_blocking s.to_io
     STDERR.puts "thread start #{Thread.current.object_id}/#{s.object_id}/#{ssl_sock.object_id}"

     while true
       STDERR.puts "select..."
       res = select([s, ssl_sock])

       unless res.nil?

         for rsock in res[0]
           #delete closed connections
           if rsock.eof? || ssl_sock.closed?
             s.close
             ssl_sock.close
             Thread.current.terminate
           end

           if rsock == s
             STDERR.puts "reading s..."
             buf = s.gets
             STDERR.puts "read: <#{ buf.inspect }>"
             #buf = s.read unless s.ready?
             #STDERR.puts "s: \n#{send}"
             #ssl_sock.write buf unless buf.nil? || buf.empty?
           end

           if rsock == ssl_sock
             STDERR.puts "read ssl"
             buf = rsock.read
             STDERR.puts "ssl: \n#{send}"
             s.write buf unless buf.nil? || buf.empty?
           end

         end #for
       end #unless
     end #while true
   end #Thread.start
end #while

perhaps networking is fubar on your machine? any silly virus software running?

regards.

-a

···

On Mon, 26 Jun 2006, Antonin AMAND wrote:

Here is the full code.

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

Francis Cianfrocca wrote:

The goal is to provide a https tunnel. In order to use iCal with ssl

socket.
<<<

Try the eventmachine library. Can probably accomplish this goal with
much
less code.

I will look at this but I would like to know why this isn't working.

Thanks anyway.

···

--
Posted via http://www.ruby-forum.com/\.

unknown wrote:

···

On Mon, 26 Jun 2006, Antonin AMAND wrote:

Here is the full code.

if you make the mod i suggested it works fine:

It actually do work. I don't know why it wasn't i've tried with gets
dozens of times. Anyway, it's working fine now but is very very slow,
the ssl socket respond with some strange delay (2-3 sec). Is it related
with buffering ??

--
Posted via http://www.ruby-forum.com/\.

Have you thought about using an ssh-tunnel. Prob would be faster.

···

On Mon, Jun 26, 2006 at 11:54:11PM +0900, Antonin Amand wrote:

unknown wrote:
> On Mon, 26 Jun 2006, Antonin AMAND wrote:
>
>> Here is the full code.
>
> if you make the mod i suggested it works fine:

It actually do work. I don't know why it wasn't i've tried with gets
dozens of times. Anyway, it's working fine now but is very very slow,
the ssl socket respond with some strange delay (2-3 sec). Is it related
with buffering ??

ipv6? dns issues? other than that i dunno - it's fast on my machine.

btw. did you know about this

   http://icalendar.rubyforge.org/

might help along the way - or it might not...

cheers.

-a

···

On Mon, 26 Jun 2006, Antonin Amand wrote:

unknown wrote:

On Mon, 26 Jun 2006, Antonin AMAND wrote:

Here is the full code.

if you make the mod i suggested it works fine:

It actually do work. I don't know why it wasn't i've tried with gets
dozens of times. Anyway, it's working fine now but is very very slow,
the ssl socket respond with some strange delay (2-3 sec). Is it related
with buffering ??

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

unknown wrote:

···

On Mon, Jun 26, 2006 at 11:54:11PM +0900, Antonin Amand wrote:

with buffering ??

Have you thought about using an ssh-tunnel. Prob would be faster.

iCal require http

--
Posted via http://www.ruby-forum.com/\.

unknown wrote:

with buffering ??

ipv6? dns issues? other than that i dunno - it's fast on my machine.

I'll check

btw. did you know about this

   http://icalendar.rubyforge.org/

Not helping, but very interesting.

Thx.

···

On Mon, 26 Jun 2006, Antonin Amand wrote:

--
Posted via http://www.ruby-forum.com/\.

Give stunnel ( http://www.stunnel.org/ ) a try. It does what you are
trying to do, is very fast, and works great!

--Aaron

···

On Tue, Jun 27, 2006 at 12:46:28AM +0900, Antonin Amand wrote:

unknown wrote:
> On Mon, Jun 26, 2006 at 11:54:11PM +0900, Antonin Amand wrote:
>> with buffering ??
> Have you thought about using an ssh-tunnel. Prob would be faster.

iCal require http

I think I've found a part of the problem.

Reading the openssl library source code I discover that SSLSocket are
non-blocking IO.

I'm not very familiar with the non-blocking IO. How would I now when I
should read or not without an active loop ?

Thank.

Antonin.

···

--
Posted via http://www.ruby-forum.com/.

Aaron Patterson wrote:

···

On Tue, Jun 27, 2006 at 12:46:28AM +0900, Antonin Amand wrote:

unknown wrote:
> On Mon, Jun 26, 2006 at 11:54:11PM +0900, Antonin Amand wrote:
>> with buffering ??
> Have you thought about using an ssh-tunnel. Prob would be faster.

iCal require http

Give stunnel ( http://www.stunnel.org/ ) a try. It does what you are
trying to do, is very fast, and works great!

--Aaron

Seems to be. If I've seen that sooner I may not have start this program
and I'll probably use it at last. But for now I'll continue searching a
solution to my problem, I'm not giving up !

Thank you.

--
Posted via http://www.ruby-forum.com/\.