/
client.rb
123 lines (110 loc) · 3.57 KB
/
client.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2013 Kouhei Sutou <kou@clear-code.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
require "gqtp/parser"
require "gqtp/sequential-request"
module GQTP
class Client
attr_accessor :host, :port
def initialize(options={})
@options = options.dup
@options[:host] ||= @options[:address] || "127.0.0.1"
@options[:port] ||= 10043
@connection = create_connection
end
def send(body, options={}, &block)
header = options[:header] || Header.new
header.size = body.bytesize
if block_given?
sequential_request = SequentialRequest.new
write_request = @connection.write(header.pack, body) do
sequential_request << read(&block)
end
sequential_request << write_request
sequential_request
else
@connection.write(header.pack, body)
end
end
def read(&block)
sync = !block_given?
parser = Parser.new
response_body = nil
sequential_request = SequentialRequest.new
read_header_request = @connection.read(Header.size) do |header|
parser << header
read_body_request = @connection.read(parser.header.size) do |body|
response_body = body
yield(parser.header, response_body) if block_given?
end
sequential_request << read_body_request
end
sequential_request << read_header_request
if sync
sequential_request.wait
[parser.header, response_body]
else
sequential_request
end
end
# Closes the opened connection. You can't send a new request after
# this method is called.
#
# @overload close
# Closes synchronously.
#
# @return [true]
#
# @overload close {}
# Closes asynchronously.
#
# @yield [] Calls the block when the opened connection is closed.
# @return [#wait] The request object. If you want to wait until
# the request is processed. You can send #wait message to the
# request.
def close
sync = !block_given?
sequential_request = SequentialRequest.new
quit_request = send("quit", :header => header_for_close) do
@connection.close
yield if block_given?
end
sequential_request << quit_request
if sync
sequential_request.wait
true
else
sequential_request
end
end
private
def create_connection
connection = @options[:connection] || :thread
begin
require "gqtp/connection/#{connection}"
rescue LoadError
raise ArgumentError, "unknown connection: <#{connection.inspect}>"
end
module_name = connection.to_s.capitalize
connection_module = GQTP::Connection.const_get(module_name)
connection_module::Client.new(@options)
end
def header_for_close
Header.new(:flags => Header::Flag::HEAD)
end
end
end