proxy_daemon 0.1.3 → 0.1.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d2b9074ac6f2540105b251e49fb530bfedf864e7
4
- data.tar.gz: 814414fde598324b3a3b2a06c2bcd88b2744a340
3
+ metadata.gz: 4b3331057afa6180824de6caef0c7850ce2ad626
4
+ data.tar.gz: 067c6efd89f48be51d25f8318ea66fe5c44a553f
5
5
  SHA512:
6
- metadata.gz: 4d06f6fa08f208a4537406a82dd359a134b2a8822999636c5bb2e5a58a094f65a00df7135c4d57c162c320b00d909c5acd007f4235972c1bf59002c9e19a416c
7
- data.tar.gz: 40c533a7e7930e23fd0b3bb14179bdc86704763878365441143b8062bac340e6ea00a491ee14ded9fb7abcc8c90c12b4afcadbf16db0b3368a377d3520c6a844
6
+ metadata.gz: 375d890481795fbeca35f98eaaf0dcfb1648a2fc21993a83be077aa195146881a16669d5845f62555ec0e0caf2772010e93b7944f7eba2135d67515433dbe9d2
7
+ data.tar.gz: 7e87ce478643d0261289738aeb021c03865012e28f3270c28e2b5379344ad5041c44ce5670ed9dbc3c410e35a32830d580116ce10d4710ddc73212dace5bc7c0
@@ -6,62 +6,79 @@ require 'colorize'
6
6
  module ProxyDaemon
7
7
  class Daemon
8
8
  attr_accessor :list
9
-
10
- def initialize(script, options)
11
- @script = script
12
- @proxies = ((options[:proxies].map { |proxy| proxy.gsub /\s+/, ' ' }) || []).shuffle
9
+
10
+ def initialize(script_or_parser, options = nil)
11
+ if script_or_parser.is_a? String then @script = script_or_parser
12
+ else
13
+ @script = '-'
14
+
15
+ if script_or_parser.is_a? Hash then options = script_or_parser
16
+ else @parser = script_or_parser end
17
+ end
18
+
19
+ @proxies = ((options[:proxies].map { |proxy| proxy.gsub /\s+/, ' ' }) || [])#.shuffle
13
20
  @urls = options[:urls] || []
14
- @workers = [(options[:workers] || 10), @urls.count].min
21
+ @worker_processes = (options[:worker_processes] || 10)
15
22
  @tries = options[:tries] || 4
16
-
23
+
17
24
  @threads = []
18
25
  @list = {}
19
26
  @semaphore = Mutex.new
20
27
  end
21
-
22
- def command(cmd, pipe, *params)
28
+
29
+ def command(cmd, pipe, params = {})
30
+ command = {command: cmd}.merge(params)
31
+
23
32
  Thread.current[:command] = cmd
24
- pipe.syswrite("#{cmd} #{params.join(' ')}\n")
33
+ pipe.puts(command.to_json)
25
34
  end
26
-
35
+
27
36
  def listen(pipe, try = 0)
28
- answer = (pipe.sysread(30) || '').strip
29
-
37
+ packet = JSON.parse((pipe.gets || '').strip)
38
+ raise "Empty answer from worker process" if packet.empty?
39
+ answer = packet['answer']
40
+ raise "Process: '#{answer}'" if answer == 'timeout' || answer == 'error'
41
+
30
42
  if answer == 'proxy'
31
43
  raise "Broken url: #{Thread.current[:url]}" if try > @tries
32
-
44
+
33
45
  proxy = getProxy
46
+ log "Answer: #{answer}, data: #{packet['data']}".yellow, pipe
34
47
  log "Choosing new proxy: #{(proxy || 'nil').yellow}", pipe
35
- command :proxy, pipe, proxy
36
- command :url, pipe, Thread.current[:url]
48
+ command :proxy, pipe, proxy: proxy
49
+ # command :url, pipe, url: Thread.current[:url]
37
50
  listen pipe, try+1
38
- elsif answer.empty?
39
- raise "Empty answer from worker process"
40
- elsif answer == 'timeout' || answer == 'error'
41
- raise "Process: '#{answer}'"
42
- elsif Thread.current[:command] == :url
43
- if (buf = answer.match(/^set (.+?)[\s]*:[\s]*?(.+)$/i)); @list[buf[1]] = buf[2] end
44
- log "Process: #{Thread.current[:url].cyan}: '#{answer.green}'", pipe
51
+ elsif answer == 'ok'
52
+ @semaphore.synchronize { @list.merge! packet['data'] } if packet.key? 'data'
53
+ log "Process: #{Thread.current[:url].cyan}: '#{answer.green}', data: #{packet['data'].to_json}", pipe
45
54
  else
46
- log "Answer: #{answer}".green, pipe
55
+ log "Answer: #{answer}, data: #{packet['data'].to_json}".green, pipe
47
56
  end
48
57
  end
49
-
58
+
50
59
  def worker
51
60
  IO.popen("#{@script}", 'r+') { |p|
52
61
  if (@script == '-' && p.nil?) # child process
53
- if @block.nil?
54
- $stderr.puts "[#{Process.pid}]".magenta + ' Empty block for parsing content'.red
62
+ if @block.nil? && @parser.nil?
63
+ $stderr.syswrite "[#{Process.pid}]".magenta + ' The parser is undefined and block wasn\'t given for parsing the content'.red + "\n"
64
+ $stderr.flush
65
+
55
66
  Kernel.exit!
56
67
  end
57
68
 
58
- worker = ProxyDaemon::Worker.new
59
- worker.call(&@block)
69
+ if @parser
70
+ worker = ProxyDaemon::Worker.new(@parser, @parse_method)
71
+ worker.call
72
+ elsif @block
73
+ worker = ProxyDaemon::Worker.new
74
+ worker.call(&@block)
75
+ end
60
76
  else
77
+ p.sync = true
61
78
  proxy = getProxy
62
79
  log "Starting loop with new proxy: ".green + "#{(proxy || 'nil').yellow}", p
63
- command :proxy, p, proxy
64
-
80
+ command :proxy, p, proxy: proxy
81
+
65
82
  begin
66
83
  loop do
67
84
  sleep(0.1)
@@ -74,41 +91,47 @@ module ProxyDaemon
74
91
  else
75
92
  log 'Urls count: ' + "#{@urls.length}".green + ", #{url.green}"
76
93
  Thread.current[:url] = url
77
- command :url, p, url
94
+ command :url, p, url: url
78
95
  listen p
79
96
  end
80
97
  end
81
-
98
+
82
99
  log "Finishing loop".green, p
83
100
  rescue Exception => e
84
101
  @semaphore.synchronize {
85
- log "Exception in main: " + "#{e.message.red}, '#{Thread.current[:url]}'".red, p
102
+ log "Exception in main:".red + " '#{Thread.current[:url]}'".yellow + " #{e.message.red}".red + "\n#{e.backtrace.join("\n").red}\n", p
86
103
  command :exit, p
87
104
  #puts e.backtrace
88
105
  }
89
106
  end
90
107
  end
91
108
  }
92
-
109
+
93
110
  if @urls.length > 0
94
111
  # @threads << Thread.new(&(->{worker}))
95
112
  # @threads.last.join
96
113
  worker
97
114
  end
98
115
  end
99
-
100
- def start(&block)
116
+
117
+ def start(options = nil, &block)
101
118
  @block = block if block_given?
119
+ @parse_method = options[:parse] if options && options.key?(:parse)
120
+ worker_processes = [@worker_processes, @urls.count].min
102
121
 
103
122
  begin
104
- puts "[main] Starting " + "#{@workers}".yellow + " workers:"
105
- @workers.times { |i| @threads << Thread.new(&(->{worker})) }
123
+ puts "[main] Starting " + "#{worker_processes}".yellow + " workers:"
124
+ worker_processes.times { |i| @threads << Thread.new(&(->{worker})) }
106
125
  @threads.each { |t| t.join }
107
126
  rescue Interrupt => e
108
127
  puts "[main] Interrupted by user".yellow
109
128
  end
110
129
  end
111
-
130
+
131
+ def add_urls(urls)
132
+ @semaphore.synchronize { @urls |= [*urls] }
133
+ end
134
+
112
135
  private
113
136
  def getProxy
114
137
  proxy = String.new
@@ -119,24 +142,25 @@ module ProxyDaemon
119
142
 
120
143
  proxy
121
144
  end
122
-
145
+
123
146
  def getUrl
124
147
  url = String.new
125
148
  @semaphore.synchronize { url = @urls.shift }
126
-
149
+
127
150
  url
128
151
  end
129
-
152
+
130
153
  def finished(msg, pipe = 0)
131
154
  unless @finished
132
155
  @finished = true
133
156
  @semaphore.synchronize { log msg, pipe }
134
157
  end
135
158
  end
136
-
159
+
137
160
  def log(msg, pipe = nil)
138
- unless pipe.nil? then puts "[#{pipe.pid}]".blue + " #{msg}"
139
- else puts msg end
161
+ unless pipe.nil? then $stdout.syswrite "[#{pipe.pid}]".blue + " #{msg}\n"
162
+ else $stdout.syswrite "#{msg}\n" end
163
+ $stdout.flush
140
164
  end
141
165
  end
142
- end
166
+ end
@@ -1,3 +1,3 @@
1
1
  module ProxyDaemon
2
- VERSION = '0.1.3'
2
+ VERSION = '0.1.5'
3
3
  end
@@ -6,18 +6,21 @@ require 'openssl'
6
6
  module ProxyDaemon
7
7
  class Worker
8
8
  attr_accessor :url
9
-
10
- def initialize
9
+
10
+ def initialize(parser = nil, parse_method = nil)
11
11
  @client = Net::HTTP.Proxy(nil, nil)
12
+ @parser = parser
13
+ @parse_method = parse_method
12
14
  @url = ''
13
15
  end
14
-
16
+
15
17
  def listen
16
18
  begin
17
19
  command = ''
18
20
  Timeout::timeout(6) {
19
21
  command = ($stdin.gets || String.new).strip
20
-
22
+ log ('Task: ' + command.to_s.yellow)
23
+
21
24
  if command.empty?
22
25
  log "Got empty answer from daemon, exiting...".yellow
23
26
  raise Timeout::Error
@@ -27,13 +30,16 @@ module ProxyDaemon
27
30
  answer 'timeout'
28
31
  Kernel.exit!
29
32
  end
30
-
33
+
31
34
  command
32
35
  end
33
-
34
- def answer(command)
36
+
37
+ def answer(answer, data = nil)
35
38
  begin
36
- $stdout.puts "#{command}"
39
+ pack = {answer: answer}
40
+ pack[:data] = data if data
41
+
42
+ $stdout.puts pack.to_json
37
43
  $stdout.flush
38
44
  rescue Errno::EPIPE => e
39
45
  log 'Broken pipe with daemon, exiting...'.yellow
@@ -42,7 +48,7 @@ module ProxyDaemon
42
48
  log e.inspect.red
43
49
  end
44
50
  end
45
-
51
+
46
52
  def process(url)
47
53
  begin
48
54
  uri = URI(url)
@@ -63,31 +69,30 @@ module ProxyDaemon
63
69
  @page = http.request(req)
64
70
  }
65
71
  }
66
-
72
+
67
73
  if (!@page.is_a?(Net::HTTPOK) || @page.body.empty?)
68
74
  log @page
69
75
  raise Net::HTTPBadResponse
70
76
  end
71
-
77
+
72
78
  res = parse(@page.body)
73
-
74
- if !!res == res || res.nil?; answer(res ? 'ok' : 'error')
75
- elsif res.is_a? Array; answer("set #{res[0]}:#{res[1]}")
76
- else; answer('error') end
79
+
80
+ if !!res === res || res.nil? then answer(res ? 'ok' : 'error')
81
+ else answer('ok', res) end
77
82
  rescue Timeout::Error, Errno::ETIMEDOUT, Errno::ECONNREFUSED,
78
83
  Errno::EINVAL, Errno::ECONNRESET, Errno::ENETUNREACH, SocketError, EOFError,
79
- TypeError, Net::HTTPExceptions, Net::HTTPBadResponse, OpenSSL::SSL::SSLError => e
80
- log "proxy".red + " in #{'process'.yellow}: #{e.inspect.red}"
84
+ TypeError, Zlib::BufError, Net::HTTPExceptions, Net::HTTPBadResponse, OpenSSL::SSL::SSLError => e
85
+ log 'proxy'.red + " in #{'process'.yellow}: #{e.inspect.red}"
81
86
  answer 'proxy'
82
87
  rescue Interrupt => e
83
88
  log 'Interrupted by user, exiting...'.yellow
84
89
  Kernel.exit!
85
90
  rescue Exception => e
86
- log "rescue in #{'process'.yellow}: #{e.inspect},\n#{e.backtrace.reverse.join("\n").red}"
91
+ log "rescue in #{'process'.yellow}: #{e.inspect},\n#{e.backtrace.join("\n").red}"
87
92
  answer 'error'
88
93
  end
89
94
  end
90
-
95
+
91
96
  def changeProxy(proxy)
92
97
  if proxy == 'localhost' || proxy.nil? || (proxy = proxy.split(/\s+/)).length < 2
93
98
  ENV['http_proxy'] = nil
@@ -95,42 +100,45 @@ module ProxyDaemon
95
100
  ENV['http_proxy'] = "http://#{proxy[0]}:#{proxy[1]}"
96
101
  end
97
102
  end
98
-
103
+
99
104
  def parse(body)
100
- raise NotImplementedError if @block.nil?
105
+ raise NotImplementedError if @parser.nil? && @block.nil?
101
106
 
102
- @block.call(self, body)
107
+ @block.call(self, body) if @block
108
+ @parser.send(:"parse_#{@parse_method}", self, body) if @parser
103
109
  # instance_exec body, &@block
104
110
  end
105
111
 
106
112
  def call(&block)
113
+ $stdout.sync = true
107
114
  @block = block if block_given?
108
115
  proxy = nil
109
116
 
110
117
  loop do
111
118
  begin
112
- task = listen
113
- case task
114
- when /^proxy/
115
- proxy = task.match(/^proxy\s*(.*)$/)[1]
119
+ task = JSON.parse(listen)
120
+
121
+ case task['command']
122
+ when 'proxy'
123
+ proxy = task['proxy']
116
124
  changeProxy(proxy)
117
- when /^url/
118
- @url = task.match(/^url\s+(.+)$/)[1]
125
+ process(@url) unless @url.empty?
126
+ when 'url'
127
+ @url = task['url']
119
128
  process(@url)
120
- when /^exit/
129
+ when 'exit'
121
130
  exit!
122
131
  end
123
-
124
- #$stderr.puts "[child #{Process.pid}]".magenta + ' Task: ' + task.to_s.yellow
125
132
  rescue => e
126
133
  log "rescue in #{'call'.yellow}: #{e.inspect.red}"
127
134
  answer 'error'
128
135
  end
129
136
  end
130
137
  end
131
-
138
+
132
139
  def log(msg)
133
- $stderr.puts "[child #{Process.pid}]".magenta + " #{msg}"
140
+ $stderr.syswrite "[child #{Process.pid}]".magenta + " #{msg}\n"
141
+ $stderr.flush
134
142
  end
135
143
  end
136
144
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proxy_daemon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michail Volkov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-11 00:00:00.000000000 Z
11
+ date: 2016-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -95,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
95
  version: '0'
96
96
  requirements: []
97
97
  rubyforge_project:
98
- rubygems_version: 2.5.1
98
+ rubygems_version: 2.6.4
99
99
  signing_key:
100
100
  specification_version: 4
101
101
  summary: Simple daemon for grabbing sites via proxy servers.