iodine 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of iodine might be problematic. Click here for more details.

@@ -1,24 +1,29 @@
1
1
  module Iodine
2
2
  class Http < Iodine::Protocol
3
3
  class Websockets < ::Iodine::Protocol
4
+ # initialize the websocket protocol.
4
5
  def initialize io, handler, request, ws_extentions = nil
5
6
  @handler = handler
6
7
  @ws_extentions = ws_extentions
7
8
  request[:io] = self
8
9
  super(io)
9
10
  end
11
+ # continue to initialize the websocket protocol.
10
12
  def on_open
11
13
  set_timeout 45
12
14
  @parser = {body: '', stage: 0, step: 0, mask_key: [], len_bytes: []}
13
15
  set_timeout = self.class.default_timeout
14
- @handler.on_open self if @handler.respond_to? :on_open
16
+ @handler.on_open if @handler.respond_to? :on_open
15
17
  end
18
+ # parse and handle messages.
16
19
  def on_message data
17
20
  extract_message StringIO.new(data)
18
21
  end
22
+ # handle broadcasts.
19
23
  def on_broadcast data
20
24
  @handler.on_broadcast(data) if @handler.respond_to? :on_broadcast
21
25
  end
26
+ # cleanup after closing.
22
27
  def on_close
23
28
  @handler.on_close if @handler.respond_to? :on_close
24
29
  if @ws_extentions
@@ -27,13 +32,28 @@ module Iodine
27
32
  end
28
33
  end
29
34
 
35
+ # a politer disconnection.
36
+ def go_away
37
+ write CLOSE_FRAME
38
+ close
39
+ end
40
+
41
+ # a politer disconnection during shutdown.
42
+ def on_shutdown
43
+ go_away
44
+ end
45
+
46
+ # allow Http responses to be used for sending Websocket data.
30
47
  def send_response response, finish = false
31
48
  body = response.extract_body
32
49
  send_data body
33
50
  end
34
51
  alias :stream_response :send_response
35
52
 
36
- # sends the data as one (or more) Websocket frames
53
+ # Sends the data as one (or more) Websocket frames.
54
+ #
55
+ # Use THIS method to send data using the Websocket protocol.
56
+ # Using {Iodine::Protocol#write} will bypass the Websocket data framing and send the raw data, breaking the connection.
37
57
  def send_data data, op_code = nil, fin = true, ext = 0
38
58
  return false if !data || data.empty?
39
59
  return false if @io.closed?
@@ -142,8 +162,7 @@ module Iodine
142
162
  end
143
163
  response['Sec-WebSocket-Accept'.freeze] = Digest::SHA1.base64digest(request['sec-websocket-key'.freeze] + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'.freeze)
144
164
  response.session
145
- # Iodine.logger << "#{@request[:client_ip]} [#{Time.now.utc}] - #{@connection.object_id} Upgraded HTTP to WebSockets.\n"
146
- # request.io.handler.send_response response
165
+ # Iodine.log "#{@request[:client_ip]} [#{Time.now.utc}] - #{@connection.object_id} Upgraded HTTP to WebSockets.\n"
147
166
  response.finish
148
167
  self.new(io.io, handler, request, ws_extentions)
149
168
  return true
@@ -102,52 +102,37 @@ module Iodine
102
102
  begin
103
103
  @server = ::TCPServer.new(@bind, @port)
104
104
  rescue => e
105
- Iodine.fatal e.message
106
- Iodine.fatal "Running existing tasks and exiting."
107
- @stop = true
105
+ fatal e.message
106
+ fatal "Running existing tasks and exiting."
107
+ Process.kill("INT", 0)
108
108
  next
109
109
  end
110
110
  shut_down_proc = Proc.new {|protocol| protocol.on_shutdown ; protocol.close }
111
111
  on_shutdown do
112
- @logger << "Stopping to listen on port #{@port} and shutting down.\n"
112
+ log "Stopping to listen on port #{@port} and shutting down.\n"
113
113
  @server.close unless @server.closed?
114
114
  @ios.values.each {|p| run p, &shut_down_proc }
115
115
  end
116
116
  ::Iodine::Base::Listener.accept(@server, false)
117
- @logger << "Iodine #{VERSION} is listening on port #{@port}#{ ' to SSL/TLS connections.' if @ssl}\n"
117
+ log "Iodine #{VERSION} is listening on port #{@port}#{ ' to SSL/TLS connections.' if @ssl}\n"
118
118
  if @spawn_count && @spawn_count.to_i > 1 && Process.respond_to?(:fork)
119
- @logger << "Server will run using #{@spawn_count.to_i} processes - Spawning #{@spawn_count.to_i - 1 } more processes.\n"
119
+ log "Server will run using #{@spawn_count.to_i} processes - Spawning #{@spawn_count.to_i - 1 } more processes.\n"
120
120
  (@spawn_count.to_i - 1).times do
121
121
  Process.fork do
122
- @logger << "Spawned process: #{Process.pid}.\n"
123
- on_shutdown { @logger << "Shutting down process #{Process.pid}.\n" }
124
- threads = []
122
+ log "Spawned process: #{Process.pid}.\n"
123
+ on_shutdown { log "Shutting down process #{Process.pid}.\n" }
125
124
  @queue.clear
126
125
  @queue << REACTOR
127
- @thread_count.times { threads << Thread.new { cycle } }
128
- unless @stop
129
- old_int_trap = trap('INT') { throw :stop; trap('INT', old_int_trap) if old_int_trap }
130
- old_term_trap = trap('TERM') { throw :stop; trap('TERM', old_term_trap) if old_term_trap }
131
- catch(:stop) { sleep }
132
- @stop = true
133
- # setup exit timeout.
134
- threads.each {|t| Thread.new {sleep 25; t.kill; t.kill } }
135
- end
136
- threads.each {|t| t.join rescue true }
126
+ startup false, true
137
127
  end
138
128
  end
139
129
 
140
130
  end
141
- @logger << "Press ^C to stop the server.\n"
131
+ log "Press ^C to stop the server.\n"
142
132
  else
143
- @logger << "Iodine #{VERSION} is running.\n"
144
- on_shutdown do
145
- @logger << "Iodine says goodbye.\n"
146
- end
147
- @logger << "Press ^C to stop the cycling.\n"
133
+ log "Iodine #{VERSION} is running.\n"
134
+ log "Press ^C to stop the cycling.\n"
148
135
  end
149
- old_int_trap = trap('INT') { throw :stop; trap('INT', old_int_trap) if old_int_trap }
150
- old_term_trap = trap('TERM') { throw :stop; trap('TERM', old_term_trap) if old_term_trap }
151
136
  @queue << REACTOR
152
137
  end
153
138
  end
@@ -2,7 +2,7 @@ module Iodine
2
2
  public
3
3
 
4
4
  # Gets the logging object and allows you to call logging methods (i.e. `Iodine.log.info "Running"`).
5
- def logger log = nil
5
+ def logger
6
6
  @logger
7
7
  end
8
8
 
@@ -36,6 +36,12 @@ module Iodine
36
36
  @logger.fatal data, &block if @logger
37
37
  data
38
38
  end
39
+ # logs a raw text
40
+ # @return [String] always returns the Object sent to the log.
41
+ def log raw_text
42
+ @logger << raw_text if @logger
43
+ raw_text
44
+ end
39
45
 
40
46
 
41
47
  protected
@@ -71,6 +71,9 @@ module Iodine
71
71
  nil
72
72
  end
73
73
  alias :disconnect :close
74
+ def closed?
75
+ @io.closed?
76
+ end
74
77
 
75
78
  # reads from the IO up to the specified number of bytes (defaults to ~2Mb).
76
79
  def read size = 2_097_152
@@ -103,7 +106,7 @@ module Iodine
103
106
  #
104
107
  # This can be used locally but not across processes.
105
108
  def id
106
- @id ||= @io.to_io.to_s(16)
109
+ @id ||= @io.to_io.object_id.to_s(16)
107
110
  end
108
111
 
109
112
  # returns an [Enumerable](http://ruby-doc.org/core-2.2.3/Enumerable.html) with all the active connections.
@@ -12,6 +12,8 @@ module Iodine
12
12
  # Sets/gets how many times a timed event repeats.
13
13
  # If set to false or -1, the timed event will repead until the application quits.
14
14
  attr_accessor :repeat_limit
15
+ # Allows you to acess or change the timer's Proc object.
16
+ attr_accessor :job
15
17
 
16
18
  # Initialize a timed event.
17
19
  def initialize reactor, interval, repeat_limit = -1, args=[], job=nil
@@ -68,7 +70,6 @@ module Iodine
68
70
  #
69
71
  # accepts:
70
72
  # seconds:: the minimal amount of seconds to wait before calling the handler's `call` method.
71
- # limit:: the amount of times the event should repeat itself. The event will repeat every x amount of `seconds`. The event will repeat forever if limit is set to false.
72
73
  # *arg:: any arguments that will be passed to the handler's `call` method.
73
74
  # &block:: the block to execute.
74
75
  #
@@ -79,8 +80,8 @@ module Iodine
79
80
  # Timed event's time of execution is dependant on the workload and continuous uptime of the process (timed events AREN'T persistent unless you save and reload them yourself).
80
81
  #
81
82
  # @return [Iodine::TimedEvent] returns the new TimedEvent object.
82
- def run_every seconds, limit = -1, *args, &block
83
- timed_job seconds, limit, args, block
83
+ def run_every seconds, *args, &block
84
+ timed_job seconds, -1, args, block
84
85
  end
85
86
 
86
87
  protected
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -1,3 +1,3 @@
1
1
  require 'iodine/http'
2
2
 
3
- ::Rack::Handler.register( 'iodine', 'Iodine::Base::Rack') if defined?(::Rack)
3
+ ::Rack::Handler.register( 'iodine', 'Iodine::Http::Rack') if defined?(::Rack)
@@ -20,28 +20,25 @@ require "iodine/http"
20
20
  Iodine.protocol.on_http { "Hello World!" }
21
21
 
22
22
 
23
- class WSChatServer
24
- def initialize nickname
25
- @nickname = nickname || "unknown"
26
- end
27
- def on_open protocol
28
- @io = protocol
29
- @io.broadcast "#{@nickname} has joined the chat!"
30
- @io << "Welcome #{@nickname}, you have joined the chat!"
31
- end
32
- def on_message data
33
- @io.broadcast "#{@nickname} >> #{data}"
34
- @io << ">> #{data}"
35
- end
36
- def on_broadcast data
37
- @io << data
38
- end
39
- def on_close
40
- @io.broadcast "#{@nickname} has left the chat!"
41
- end
23
+ class WSChatServer < Iodine::Http::WebsocketHandler
24
+ def on_open
25
+ @nickname = request.params[:nickname] || "unknown"
26
+ broadcast "#{@nickname} has joined the chat!"
27
+ write "Welcome #{@nickname}, you have joined the chat!"
28
+ end
29
+ def on_message data
30
+ broadcast "#{@nickname} >> #{data}"
31
+ write ">> #{data}"
32
+ end
33
+ def on_broadcast data
34
+ write data
35
+ end
36
+ def on_close
37
+ broadcast "#{@nickname} has left the chat!"
38
+ end
42
39
  end
43
40
 
44
- Iodine::Http.on_websocket { |request, response| WSChatServer.new request.params[:name]}
41
+ Iodine::Http.on_websocket WSChatServer
45
42
 
46
43
  Process.fork do
47
44
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iodine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-19 00:00:00.000000000 Z
11
+ date: 2015-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler