Module: UV

Defined in:
lib/uv-rays/ping.rb,
lib/uv-rays.rb,
lib/uv-rays/version.rb,
lib/uv-rays/scheduler.rb,
lib/uv-rays/connection.rb,
lib/uv-rays/tcp_server.rb,
lib/uv-rays/http/parser.rb,
lib/uv-rays/http/request.rb,
lib/uv-rays/http/encoding.rb,
lib/uv-rays/http_endpoint.rb,
lib/uv-rays/scheduler/time.rb,
lib/uv-rays/abstract_tokenizer.rb,
lib/uv-rays/buffered_tokenizer.rb

Overview

BufferedTokenizer takes a delimiter upon instantiation. It allows input to be spoon-fed from some outside source which receives arbitrary length datagrams which may-or-may-not contain the token by which entities are delimited.

Examples:

Using BufferedTokernizer to parse lines out of incoming data


module LineBufferedConnection
    def receive_data(data)
        (@buffer ||= BufferedTokenizer.new(delimiter: "\n")).extract(data).each do |line|
            receive_line(line)
        end
    end
end

Defined Under Namespace

Modules: Http Classes: AbstractTokenizer, BufferedTokenizer, Connection, CookieJar, DatagramConnection, HttpEndpoint, InboundConnection, OneShot, OutboundConnection, Ping, Repeat, ScheduledEvent, Scheduler, TcpConnection, TcpServer

Constant Summary collapse

VERSION =
'2.4.7'

Class Method Summary collapse

Class Method Details

.attach_server(sock, handler, *args) ⇒ Object

Raises:

  • (ThreadError)


68
69
70
71
72
73
74
75
76
# File 'lib/uv-rays.rb', line 68

def self.attach_server(sock, handler, *args)
    thread = reactor   # Get the reactor running on this thread
    raise ThreadError, "There is no Libuv reactor running on the current thread" if thread.nil?

    klass = klass_from_handler(InboundConnection, handler, *args)
    sd = sock.respond_to?(:fileno) ? sock.fileno : sock

    UV::TcpServer.new thread, sd, sd, klass, *args
end

.connect(server, port, handler, *args) ⇒ Object



52
53
54
55
56
57
58
# File 'lib/uv-rays.rb', line 52

def self.connect(server, port, handler, *args)
    klass = klass_from_handler(OutboundConnection, handler, *args)

    c = klass.new server, port
    c.post_init *args
    c
end

.klass_from_handler(klass, handler = nil, *args) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/uv-rays.rb', line 28

def self.klass_from_handler(klass, handler = nil, *args)
    klass = if handler and handler.is_a?(Class)
        raise ArgumentError, "must provide module or subclass of #{klass.name}" unless klass >= handler
        handler
    elsif handler
        begin
            handler::UR_CONNECTION_CLASS
        rescue NameError
            handler::const_set(:UR_CONNECTION_CLASS, Class.new(klass) {include handler})
        end
    else
        klass
    end

    arity = klass.instance_method(:post_init).arity
    expected = arity >= 0 ? arity : -(arity + 1)
    if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
        raise ArgumentError, "wrong number of arguments for #{klass}#post_init (#{args.size} for #{expected})"
    end

    klass
end

.open_datagram_socket(handler, server = nil, port = nil, *args) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/uv-rays.rb', line 78

def self.open_datagram_socket(handler, server = nil, port = nil, *args)
    klass = klass_from_handler(DatagramConnection, handler, *args)

    c = klass.new server, port
    c.post_init *args
    c
end

.start_server(server, port, handler, *args) ⇒ Object

Raises:

  • (ThreadError)


60
61
62
63
64
65
66
# File 'lib/uv-rays.rb', line 60

def self.start_server(server, port, handler, *args)
    thread = reactor   # Get the reactor running on this thread
    raise ThreadError, "There is no Libuv reactor running on the current thread" if thread.nil?

    klass = klass_from_handler(InboundConnection, handler, *args)
    UV::TcpServer.new thread, server, port, klass, *args
end

.try_connect(tcp, handler, server, port) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/uv-rays/connection.rb', line 6

def self.try_connect(tcp, handler, server, port)
    if IPAddress.valid? server
        tcp.finally { handler.on_close }
        tcp.progress { |*data| handler.on_read(*data) }
        tcp.connect server, port do
            tcp.enable_nodelay
            tcp.start_tls(handler.using_tls) if handler.using_tls

            # on_connect could call use_tls so must come after start_tls
            handler.on_connect(tcp)
            tcp.start_read
        end
    else
        tcp.reactor.lookup(server, wait: false).then(
            proc { |result|
                UV.try_connect(tcp, handler, result[0][0], port)
            },
            proc { |failure|
                # TODO:: Log error on reactor
                handler.on_close
            }
        )
    end
end