rubyment 0.5.25471659 → 0.6.25484655
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rubyment.rb +522 -9
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10899b656c79527134e55de8433e25dd800660c1
|
4
|
+
data.tar.gz: 1ebc15afed675c406830ebca48e68ff683a1f3eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40061cd1e9adb1331d22821109720eab4313b40af0da7605d06ebb10dd9745bebab219f8c2cba250e910d279f66a5f0711b0b496075f8869258b75b81764ed42
|
7
|
+
data.tar.gz: 778db1047917e439d7a75bcaec5c87bc90f9a762511b753fa9a847b83cc2666de94411b9460639def90aa73547c73fded6109f7850971b023e8b73aab6ef1f49
|
data/lib/rubyment.rb
CHANGED
@@ -1,5 +1,34 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
|
4
|
+
class String
|
5
|
+
# checks if string is non neutral element.
|
6
|
+
#
|
7
|
+
# data from shell input can't be nil
|
8
|
+
# it will be an "" string. this
|
9
|
+
# function interprets "" as false
|
10
|
+
#
|
11
|
+
# @return [String, nil] self or nil
|
12
|
+
def nne
|
13
|
+
!self.empty? && self || nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
class Fixnum
|
19
|
+
# checks if Fixnum is non neutral element.
|
20
|
+
#
|
21
|
+
# data from shell input can't be nil
|
22
|
+
# it will be an 0 string. this
|
23
|
+
# function interprets 0 as false
|
24
|
+
#
|
25
|
+
# @return [Fixnum, nil] self or nil
|
26
|
+
def nne
|
27
|
+
!self.zero? && self || nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
3
32
|
# Collection of Ruby functions
|
4
33
|
# * output
|
5
34
|
# normally outputs to STDERR, with
|
@@ -22,6 +51,101 @@ class Rubyment
|
|
22
51
|
end
|
23
52
|
|
24
53
|
|
54
|
+
# creates a Proc out of a block
|
55
|
+
def bl *args, &block
|
56
|
+
block ||= lambda {}
|
57
|
+
# Proc.new &block
|
58
|
+
Proc.new { block.call *args }
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# creates a Proc out of a block,
|
63
|
+
# will capture all exceptions
|
64
|
+
# inside that block and ignore it
|
65
|
+
# returns nil
|
66
|
+
def blef *args, &block
|
67
|
+
# bl exception free
|
68
|
+
block ||= lambda {}
|
69
|
+
bl {
|
70
|
+
begin
|
71
|
+
block.call *args
|
72
|
+
rescue => e
|
73
|
+
end
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
# creates a Proc out of a block,
|
79
|
+
# will capture all exceptions
|
80
|
+
# inside that block and ignore it
|
81
|
+
# will return an array having
|
82
|
+
# the backtrace (as String) as
|
83
|
+
# the first member and the
|
84
|
+
# the exception as the second.
|
85
|
+
def bloe *args, &block
|
86
|
+
block ||= lambda {}
|
87
|
+
bl {
|
88
|
+
begin
|
89
|
+
block.call *args
|
90
|
+
rescue => e
|
91
|
+
stderr = @memory[:stderr]
|
92
|
+
rv = [e.backtrace.join("\n"), e]
|
93
|
+
stderr.puts "#{__method__} exception backtrace:"
|
94
|
+
stderr.puts rv[0]
|
95
|
+
stderr.puts "#{__method__} exception message:"
|
96
|
+
stderr.puts rv[1]
|
97
|
+
rv
|
98
|
+
end
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
# runs a block error free
|
104
|
+
# (returns nil if exception happens)
|
105
|
+
def runef *args, &block
|
106
|
+
(blef &block).call *args
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# runs a block error free, in
|
111
|
+
# a different Thread. the Thread object
|
112
|
+
# is returned (call .join on it to
|
113
|
+
# wait for its completion)
|
114
|
+
# (the Thread itself returns nil if exception happens)
|
115
|
+
def runef_threaded *args, &block
|
116
|
+
Thread.start(*args) {|*args|
|
117
|
+
runef *args, &block
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
# runs a block error free
|
123
|
+
# (if exception happens,
|
124
|
+
# will return an array having
|
125
|
+
# the backtrace (as String) as
|
126
|
+
# the first member and the
|
127
|
+
# the Exception object as the second).
|
128
|
+
def runoe *args, &block
|
129
|
+
(bloe &block).call *args
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
# runs a block error free, in
|
134
|
+
# a different Thread. the Thread object
|
135
|
+
# is returned (call .join on it to
|
136
|
+
# wait for its completion)
|
137
|
+
# (if exception happens, the thread
|
138
|
+
# itself will return an array having
|
139
|
+
# the backtrace (as String) as
|
140
|
+
# the first member and the
|
141
|
+
# the Exception object as the second).
|
142
|
+
def runoe_threaded *args, &block
|
143
|
+
Thread.start(*args) {|*args|
|
144
|
+
runoe *args, &block
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
|
25
149
|
# invoke first arg with following args
|
26
150
|
# used by initialize
|
27
151
|
def invoke args=ARGV
|
@@ -60,7 +184,7 @@ class Rubyment
|
|
60
184
|
:stdout => STDOUT,
|
61
185
|
:stdin => STDIN,
|
62
186
|
:time => Time.now,
|
63
|
-
:major_version => "0.
|
187
|
+
:major_version => "0.6",
|
64
188
|
:basic_version => (Time.now.to_i / 60), # new one every minute
|
65
189
|
:filepath => __FILE__,
|
66
190
|
:running_dir => Dir.pwd,
|
@@ -70,6 +194,7 @@ class Rubyment
|
|
70
194
|
:static_separator_key => "strings_having_this" + "_string_not_guaranteed_to_work",
|
71
195
|
:static_end_key => "strings_havinng_this_string" + "_also_not_guaranteed_to_work",
|
72
196
|
:static_separator_key_per_execution => "strings_having_this" + "_string_not_guaranteed_to_work" + (Proc.new {}).to_s + Time.now.to_s,
|
197
|
+
:threads => [Thread.current]
|
73
198
|
}
|
74
199
|
@memory.update memory.to_h
|
75
200
|
invoke @memory[:invoke].to_a
|
@@ -115,30 +240,81 @@ class Rubyment
|
|
115
240
|
end
|
116
241
|
|
117
242
|
|
243
|
+
# reads a uri (if 'open-uri' available, otherwise, just do a normal File.read)
|
244
|
+
# @param [Array] args, an +Array+ whose elements are expected to be:
|
245
|
+
# +uri+:: [String, nil] uri or path of the file
|
246
|
+
# +username+:: [String] basic http authentication username
|
247
|
+
# +password+:: [String] basic http authentication password
|
248
|
+
# +return_on_rescue+:: [Object] a default to return in the case of exceptions raised
|
249
|
+
# +return_on_directory_given+:: [Object] a default to return in the case uri is a directory. Defaults to true
|
250
|
+
#
|
251
|
+
# @return [String, Object] read data (or +return_on_rescue+)
|
252
|
+
def file_read args=ARGV
|
253
|
+
uri, username, password, return_on_rescue, return_on_directory_given = args
|
254
|
+
(require 'open-uri') && open_uri = true
|
255
|
+
file_is_directory = File.directory?(uri)
|
256
|
+
return_on_directory_given ||= true
|
257
|
+
contents = !(file_is_directory) && open_uri && (
|
258
|
+
begin
|
259
|
+
open(uri, :http_basic_authentication => [username, password]).read
|
260
|
+
rescue => e
|
261
|
+
return_on_rescue
|
262
|
+
end
|
263
|
+
) || (!open_uri) && (
|
264
|
+
begin
|
265
|
+
File.read uri
|
266
|
+
rescue => e
|
267
|
+
return_on_rescue
|
268
|
+
end
|
269
|
+
) || (file_is_directory) && (return_on_directory_given)
|
270
|
+
end
|
271
|
+
|
272
|
+
|
118
273
|
# if file is a nonexisting filepath, or by any reason
|
119
274
|
# throws any exception, it will be treated as contents
|
120
275
|
# instead, and the filename will treated as ""
|
121
276
|
# file can be a url, if 'open-uri' is available.
|
122
|
-
|
277
|
+
# extension: before file couldn't be a directory. now it can.
|
278
|
+
# planned improvement: use file_read instead
|
279
|
+
# @param [Array] args, an +Array+ whose elements are expected to be:
|
280
|
+
# +file+:: [String] uri or path of the file
|
281
|
+
# +dir+:: [String] dir where to backup file
|
282
|
+
# +append+:: [String] append this string to the end of file
|
283
|
+
# +prepend+:: [String] append this string to the beginning of file
|
284
|
+
# +permissions+:: [Integer, nil] writes the file with this mode (preserves if nil)
|
285
|
+
# @return [String] file contents
|
286
|
+
def file_backup file = __FILE__ , dir = '/tmp/', append = ('-' + Time.now.hash.abs.to_s), prepend='/', permissions = nil
|
287
|
+
default_permissions = 0755
|
123
288
|
stderr = @memory[:stderr]
|
124
289
|
debug = @memory[:debug]
|
125
290
|
(require 'open-uri') && open_uri = true
|
126
291
|
require 'fileutils'
|
127
292
|
file_is_filename = true
|
128
|
-
|
293
|
+
file_is_directory = File.directory?(file)
|
294
|
+
open_uri && (!file_is_directory) && (
|
129
295
|
contents = open(file).read rescue (file_is_filename = false) || file
|
130
|
-
) || (
|
296
|
+
) || (!file_is_directory) && (
|
131
297
|
contents = File.read file rescue (file_is_filename = false) || file
|
132
298
|
)
|
133
299
|
debug && (stderr.puts "location = dir:#{dir} + prepend:#{prepend} + (#{file_is_filename} && #{file} || '' ) + #{append}")
|
134
300
|
location = dir + prepend + (file_is_filename && file || '' ) + append
|
135
301
|
debug && (stderr.puts "FileUtils.mkdir_p File.dirname #{location}")
|
136
302
|
FileUtils.mkdir_p File.dirname location # note "~" doesn't work
|
137
|
-
|
303
|
+
file_is_directory && FileUtils.mkdir_p(location) || (
|
304
|
+
File.write location, contents
|
305
|
+
)
|
306
|
+
permissions ||= file_permissions_octal file
|
307
|
+
File.chmod permissions, location
|
138
308
|
contents
|
139
309
|
end
|
140
310
|
|
141
311
|
|
312
|
+
# same interface as file_backup, but append and prepend defaults are empty.
|
313
|
+
def file_copy file = __FILE__, dir = '/tmp/', append = '', prepend='', permissions = nil
|
314
|
+
file_backup file, dir, append, prepend, default_permissions
|
315
|
+
end
|
316
|
+
|
317
|
+
|
142
318
|
# returns a string having the current backtrace, for debugging.
|
143
319
|
def backtrace
|
144
320
|
Thread.current.backtrace.join("\n")
|
@@ -163,7 +339,7 @@ class Rubyment
|
|
163
339
|
# [ name (String), object (Object) ]
|
164
340
|
# returns:
|
165
341
|
# method_object (Method)
|
166
|
-
def
|
342
|
+
def to_object_method args=ARGV
|
167
343
|
stderr = @memory[:stderr]
|
168
344
|
name, object = containerize args
|
169
345
|
begin
|
@@ -189,7 +365,7 @@ class Rubyment
|
|
189
365
|
stderr = @memory[:stderr]
|
190
366
|
method, object, *call_args = containerize args
|
191
367
|
object ||= self
|
192
|
-
method =
|
368
|
+
method = to_object_method [method, object]
|
193
369
|
call_args = call_args && (containerize call_args)
|
194
370
|
begin
|
195
371
|
call_args && (method.call *call_args) || method.call
|
@@ -404,8 +580,6 @@ class Rubyment
|
|
404
580
|
stdin = @memory[:stdin]
|
405
581
|
static_separator_key_per_execution = @memory[:static_separator_key_per_execution]
|
406
582
|
require "io/console"
|
407
|
-
# puts backtrace
|
408
|
-
# p args.map {|e| e.to_s[0..15] }
|
409
583
|
stderr.print "multiline[enter + control-D to stop]:"
|
410
584
|
args.shift.to_s.b.split(static_separator_key_per_execution).first || stdin.noecho{ stdin.readlines}.join.chomp
|
411
585
|
end
|
@@ -1822,6 +1996,345 @@ require '#{gem_name}'
|
|
1822
1996
|
end
|
1823
1997
|
|
1824
1998
|
|
1999
|
+
# test file_backup when file is a dir
|
2000
|
+
def test__file_backup__when_file_is_dir args=ARGV
|
2001
|
+
require 'fileutils'
|
2002
|
+
dest_dir, filename, append, prepend, keep_new = args
|
2003
|
+
filename ||= "testing-" + Time.now.hash.abs.to_s + ""
|
2004
|
+
dest_dir ||= "/tmp/"
|
2005
|
+
append ||= ""
|
2006
|
+
prepend ||= ""
|
2007
|
+
filename += "/"
|
2008
|
+
expected_new_dir = dest_dir + filename
|
2009
|
+
existing_dir = (file_read [filename, nil, nil, nil])
|
2010
|
+
FileUtils.mkdir_p filename
|
2011
|
+
file_backup filename, dest_dir, append, prepend
|
2012
|
+
filename_test = File.directory? filename
|
2013
|
+
expected_new_dir_test = File.directory? expected_new_dir
|
2014
|
+
original_permissions = file_permissions_octal filename
|
2015
|
+
new_permissions = file_permissions_octal expected_new_dir
|
2016
|
+
judgement =
|
2017
|
+
[
|
2018
|
+
[filename_test, expected_new_dir_test, "File.directory?"],
|
2019
|
+
[original_permissions, new_permissions, "file_permissions"],
|
2020
|
+
].map(&method("expect_equal")).all?
|
2021
|
+
(!existing_dir) && (FileUtils.rmdir filename)
|
2022
|
+
(!keep_new) && (FileUtils.rmdir expected_new_dir)
|
2023
|
+
end
|
2024
|
+
|
2025
|
+
|
2026
|
+
# test file_backup (just like a copy)
|
2027
|
+
def test__file_backup args=ARGV
|
2028
|
+
dest_dir, filename, append, prepend, file_contents, user, pw, keep_new = args
|
2029
|
+
filename ||= "testing-" + Time.now.hash.abs.to_s + ""
|
2030
|
+
dest_dir ||= "/tmp/"
|
2031
|
+
append ||= ""
|
2032
|
+
prepend ||= ""
|
2033
|
+
expected_new_filename = dest_dir + filename
|
2034
|
+
existing_file = (file_read [filename, nil, user, pw])
|
2035
|
+
file_contents ||= existing_file || "contents_of:#{filename}"
|
2036
|
+
File.write filename, file_contents
|
2037
|
+
file_backup filename, dest_dir, append, prepend
|
2038
|
+
new_file_contents = File.read expected_new_filename
|
2039
|
+
original_permissions = file_permissions_octal filename
|
2040
|
+
new_permissions = file_permissions_octal expected_new_filename
|
2041
|
+
judgement =
|
2042
|
+
[
|
2043
|
+
[file_contents, new_file_contents, "file_contents"],
|
2044
|
+
[original_permissions, new_permissions, "file_permissions"],
|
2045
|
+
].map(&method("expect_equal")).all?
|
2046
|
+
(!existing_file) && (FileUtils.rm filename)
|
2047
|
+
(!keep_new) && (FileUtils.rm expected_new_filename)
|
2048
|
+
end
|
2049
|
+
|
2050
|
+
|
2051
|
+
# same as test__file_backup__when_file_is_dir, but backup is not removed.
|
2052
|
+
def test__file_backup__when_file_is_dir__but_keep args=ARGV
|
2053
|
+
dest_dir, filename, append, prepend, dont_keep_new = args
|
2054
|
+
test__file_backup__when_file_is_dir [dest_dir, filename, append, prepend, !dont_keep_new]
|
2055
|
+
end
|
2056
|
+
|
2057
|
+
|
2058
|
+
# same as test__file_backup, but backup is not removed.
|
2059
|
+
def test__file_backup__but_keep args=ARGV
|
2060
|
+
dest_dir, filename, append, prepend, file_contents, user, pw, dont_keep_new = args
|
2061
|
+
test__file_backup [dest_dir, filename, append, prepend, file_contents, user, pw, !dont_keep_new]
|
2062
|
+
end
|
2063
|
+
|
2064
|
+
|
2065
|
+
# returns a method object out of a string or a method object,
|
2066
|
+
# in a polymorphic style.
|
2067
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2068
|
+
# +method_name_or_method+:: [String, Method] method name or method object
|
2069
|
+
#
|
2070
|
+
# @return [Method] a method
|
2071
|
+
def to_method args = ARGV
|
2072
|
+
method_name_or_method, reserved = args
|
2073
|
+
method_name_or_method.respond_to?(:call) && method_name_or_method || method(method_name_or_method)
|
2074
|
+
end
|
2075
|
+
|
2076
|
+
|
2077
|
+
# echoes the processing arg
|
2078
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2079
|
+
# +processing_arg+:: [String]
|
2080
|
+
#
|
2081
|
+
# @return [String] +processing_arg+
|
2082
|
+
def echo args = ARGV
|
2083
|
+
args.first
|
2084
|
+
end
|
2085
|
+
|
2086
|
+
|
2087
|
+
# calls a function with the processing arg
|
2088
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2089
|
+
# +processing_arg+:: [Object]
|
2090
|
+
# +method+:: [Method, String]
|
2091
|
+
# +method_args+:: [Method, String]
|
2092
|
+
#
|
2093
|
+
# @return [String] +processing_arg+
|
2094
|
+
def transform_call args = ARGV
|
2095
|
+
processing_arg, method, method_args = args
|
2096
|
+
to_method(
|
2097
|
+
[method]).call(
|
2098
|
+
[processing_arg] + method_args
|
2099
|
+
)
|
2100
|
+
end
|
2101
|
+
|
2102
|
+
|
2103
|
+
# returns an HTTP response (1.1 200 OK by default)
|
2104
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2105
|
+
# +response+:: [String, nil] response payload (default empty)
|
2106
|
+
# +content_type+:: [String, nil] mime type of payload (default +text/plain+)
|
2107
|
+
# +version+:: [String, nil] http protocol version (+1.1+ by default)
|
2108
|
+
# +code+:: [String, nil] response code (+"200 OK"+ by default)
|
2109
|
+
# +eol+:: [String, nil]
|
2110
|
+
#
|
2111
|
+
# @return [String] http_response
|
2112
|
+
def http_OK_response args = ARGV
|
2113
|
+
payload, content_type, code, version, eol = args
|
2114
|
+
payload ||= ""
|
2115
|
+
content_type ||= "text/plain"
|
2116
|
+
version ||= "1.1"
|
2117
|
+
code ||= "200 OK"
|
2118
|
+
eol ||= "\r\n"
|
2119
|
+
[
|
2120
|
+
"HTTP/#{version} #{code}",
|
2121
|
+
"Content-Type: #{content_type};" +
|
2122
|
+
" charset=#{payload.encoding.name.downcase}",
|
2123
|
+
"Content-Length: #{payload.bytesize}",
|
2124
|
+
!keep_alive && "Connection: close"
|
2125
|
+
].join eol
|
2126
|
+
end
|
2127
|
+
|
2128
|
+
|
2129
|
+
# will call #gets on +io+ until line starts with +happy_with_request+
|
2130
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2131
|
+
# +io+:: [IO] any +IO+, like a +Socket+, returned by #TCPServer::accept
|
2132
|
+
# +debug+:: [Object] if evals to false (or empty string), won't print debug information
|
2133
|
+
# +happy_with_request+:: [String, nil] if nil, +eol+ is used.
|
2134
|
+
# +eol+:: [String] end of line
|
2135
|
+
#
|
2136
|
+
# @return [Array] array of strings having the lines read from the IO.
|
2137
|
+
def io_gets args = ARGV
|
2138
|
+
io, debug, happy_with_request = args
|
2139
|
+
happy_with_request ||= "\r\n"
|
2140
|
+
stderr = @memory[:stderr]
|
2141
|
+
debug.nne && (stderr.puts "#{__method__} starting")
|
2142
|
+
debug.nne && (stderr.puts args.inspect)
|
2143
|
+
lines = []
|
2144
|
+
(1..Float::INFINITY).
|
2145
|
+
lazy.map {|i|
|
2146
|
+
r = lines.push(io.gets).last
|
2147
|
+
debug.nne && (stderr.puts r)
|
2148
|
+
r.index(happy_with_request.to_s).to_i.nne && r
|
2149
|
+
}.find {|x| !x }
|
2150
|
+
debug.nne && (stderr.puts lines.inspect)
|
2151
|
+
debug.nne && (stderr.puts "#{__method__} returning")
|
2152
|
+
lines
|
2153
|
+
end
|
2154
|
+
|
2155
|
+
|
2156
|
+
# gets and forwards the input from one IO to a list of IOs
|
2157
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2158
|
+
# +ios_out+:: [Array] array of +IO+, where data will be written to.
|
2159
|
+
# +io_in+:: [IO] any +IO+, like a +Socket+, returned by #TCPServer::accept, where data will be read from.
|
2160
|
+
# +debug+:: [Object] if evals to false (or empty string), won't print debug information
|
2161
|
+
# +happy_with_request+:: [String, nil] if nil, +eol+ is used.
|
2162
|
+
#
|
2163
|
+
# @return [nil]
|
2164
|
+
def io_forward args = ARGV
|
2165
|
+
|
2166
|
+
ios_out,
|
2167
|
+
io_in,
|
2168
|
+
debug,
|
2169
|
+
happy_with_request,
|
2170
|
+
reserved,
|
2171
|
+
processing_method,
|
2172
|
+
processing_method_args = args
|
2173
|
+
io_gets_args = [io_in, debug, happy_with_request]
|
2174
|
+
stderr = @memory[:stderr]
|
2175
|
+
debug.nne && (stderr.puts "#{__method__} starting")
|
2176
|
+
debug.nne && (stderr.puts args.inspect)
|
2177
|
+
input = io_gets io_gets_args
|
2178
|
+
debug.nne && (stderr.puts input.inspect)
|
2179
|
+
debug.nne && (stderr.puts ios_out.class.inspect)
|
2180
|
+
processing_method ||= :echo
|
2181
|
+
processing_method_args ||= []
|
2182
|
+
processed_input = to_method(
|
2183
|
+
[processing_method]).call(
|
2184
|
+
[input] + processing_method_args
|
2185
|
+
)
|
2186
|
+
ios_out.map{ |shared_io_out|
|
2187
|
+
runoe_threaded(shared_io_out) {|io_out|
|
2188
|
+
io_out = shared_io_out
|
2189
|
+
io_out.puts processed_input
|
2190
|
+
debug.nne && (
|
2191
|
+
stderr.puts "#{io_out}: response writen."
|
2192
|
+
)
|
2193
|
+
io_out.close
|
2194
|
+
debug.nne && (
|
2195
|
+
stderr.puts "#{io_out}: IO closed."
|
2196
|
+
)
|
2197
|
+
|
2198
|
+
}
|
2199
|
+
}
|
2200
|
+
debug.nne && (stderr.puts "#{__method__} returning")
|
2201
|
+
nil
|
2202
|
+
end
|
2203
|
+
|
2204
|
+
|
2205
|
+
# gets and puts
|
2206
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2207
|
+
# +io+:: [IO] any +IO+, like a +Socket+, returned by #TCPServer::accept
|
2208
|
+
# +method_name_or_method+:: [String, Method] method name or method object
|
2209
|
+
# +debug+:: [Object] if evals to false (or empty string), won't print debug information
|
2210
|
+
# +happy_with_request+:: [String, nil] if nil, +eol+ is used.
|
2211
|
+
#
|
2212
|
+
# @return [nil]
|
2213
|
+
def io_echo args = ARGV
|
2214
|
+
io, debug, happy_with_request, reserved = args
|
2215
|
+
stderr = @memory[:stderr]
|
2216
|
+
debug.nne && (stderr.puts "#{__method__} starting")
|
2217
|
+
# io_forward [[io], io, debug, happy_with_request, reserved, :echo, []]
|
2218
|
+
io_forward [[io], io, debug, happy_with_request, reserved,
|
2219
|
+
:gsub!, [" ", "_"]
|
2220
|
+
]
|
2221
|
+
nil
|
2222
|
+
end
|
2223
|
+
|
2224
|
+
|
2225
|
+
# writes a response to an IO (e.g.: socket)
|
2226
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2227
|
+
# +method_name_or_method+:: [String, Method] method name or method object
|
2228
|
+
# +debug+:: [Object] if evals to false (or empty string), won't print debug information
|
2229
|
+
# +reserved+:: [Object] for future use
|
2230
|
+
# +args_for_http_OK_response+:: [splat] args to be forwarded to #http_OK_response (check it for specification)
|
2231
|
+
#
|
2232
|
+
# @return [nil]
|
2233
|
+
def io_http_OK_response args = ARGV
|
2234
|
+
io, debug, reserved, *args_for_http_OK_response = args
|
2235
|
+
stderr = @memory[:stderr]
|
2236
|
+
debug.nne && (stderr.puts args.inspect)
|
2237
|
+
response = http_OK_response args_for_http_OK_response
|
2238
|
+
debug.nne && (
|
2239
|
+
stderr.puts response.inspect
|
2240
|
+
)
|
2241
|
+
io.print response
|
2242
|
+
debug.nne && (stderr.puts "response writen.")
|
2243
|
+
io.close
|
2244
|
+
debug.nne && (stderr.puts "IO closed.")
|
2245
|
+
nil
|
2246
|
+
end
|
2247
|
+
|
2248
|
+
|
2249
|
+
# opens a TCP server accepting connections.
|
2250
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2251
|
+
# +listening_port+:: [String, Integer] port to listen
|
2252
|
+
# +ip_addr+:: [String, nil] ip (no hostname) to bind the server. 0, nil, false, empty string will bind to all addresses possible. 0.0.0.0 => binds to all ipv4 . ::0 to all ipv4 and ipv6
|
2253
|
+
# +reserved+:: [Object] for future use
|
2254
|
+
# +debug+:: [Object] for future use
|
2255
|
+
# +callback_method+:: [String, Method] method to call when a client connects. The method must accept a socket as parameter.
|
2256
|
+
# +callback_method_args+:: [splat] args to be given to the call_back_method
|
2257
|
+
#
|
2258
|
+
# @return [Thread] returns a Thread object looping for accepting
|
2259
|
+
# incoming connections (call join on that object for waiting for its
|
2260
|
+
# completion).
|
2261
|
+
def tcp_server_plain args = ARGV
|
2262
|
+
stderr = @memory[:stderr]
|
2263
|
+
listening_port,
|
2264
|
+
ip_addr,
|
2265
|
+
reserved,
|
2266
|
+
debug,
|
2267
|
+
callback_method,
|
2268
|
+
*callback_method_args = args
|
2269
|
+
require 'socket'
|
2270
|
+
server = TCPServer.new ip_addr, listening_port
|
2271
|
+
debug.nne && (stderr.puts server)
|
2272
|
+
Thread.start {
|
2273
|
+
loop {
|
2274
|
+
Thread.start(server.accept) { |client|
|
2275
|
+
debug.nne && (stderr.puts Thread.current)
|
2276
|
+
debug.nne && (stderr.puts client)
|
2277
|
+
runoe {
|
2278
|
+
to_method([callback_method])
|
2279
|
+
.call([client] + callback_method_args)
|
2280
|
+
}
|
2281
|
+
}
|
2282
|
+
}
|
2283
|
+
}
|
2284
|
+
end
|
2285
|
+
|
2286
|
+
|
2287
|
+
# opens a TCP client (TCPsocket) to connect to a server
|
2288
|
+
# @param [Array] +args+, an +Array+ whose elements are expected to be:
|
2289
|
+
#
|
2290
|
+
# @return [nil]
|
2291
|
+
def tcp_client_plain args = ARGV
|
2292
|
+
listening_port,
|
2293
|
+
ip_addr,
|
2294
|
+
reserved,
|
2295
|
+
debug,
|
2296
|
+
callback_method,
|
2297
|
+
*callback_method_args = args
|
2298
|
+
require 'socket'
|
2299
|
+
client = TCPSocket.new ip_addr, listening_port
|
2300
|
+
=begin
|
2301
|
+
Thread.start {
|
2302
|
+
to_method([callback_method])
|
2303
|
+
.call [client]
|
2304
|
+
}
|
2305
|
+
=end
|
2306
|
+
Thread.start {}
|
2307
|
+
end
|
2308
|
+
|
2309
|
+
|
2310
|
+
# test for tcp_server_plain
|
2311
|
+
def test__tcp_server_plain args = ARGV
|
2312
|
+
thread = tcp_server_plain [8003, "0", "", "debug", "io_echo", "debug_io_echo"]
|
2313
|
+
thread.join
|
2314
|
+
end
|
2315
|
+
|
2316
|
+
|
2317
|
+
# test for tcp_server_plain
|
2318
|
+
def test__tcp_server_plain__with_io_http_response args = ARGV
|
2319
|
+
thread = tcp_server_plain [
|
2320
|
+
8003, # listening_port
|
2321
|
+
"0", # ip_addr: all possible
|
2322
|
+
"", # reserved
|
2323
|
+
"debug_tcp_server_plain_arg",
|
2324
|
+
"io_http_OK_response",
|
2325
|
+
"debug_io_http_OK_response_arg",
|
2326
|
+
"reserved_io_http_OK_response_arg",
|
2327
|
+
"This is the response payload"
|
2328
|
+
]
|
2329
|
+
thread.join
|
2330
|
+
end
|
2331
|
+
|
2332
|
+
|
2333
|
+
# test for tcp_server_plain
|
2334
|
+
def test__tcp_server_plain__with_io_http_response args = ARGV
|
2335
|
+
end
|
2336
|
+
|
2337
|
+
|
1825
2338
|
end
|
1826
2339
|
|
1827
2340
|
(__FILE__ == $0) && Rubyment.new({:invoke => ARGV})
|