crap_server 0.0.4.2 → 0.0.5.0

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: b8f32930965a763afe13876581ab27b27c5c4803
4
- data.tar.gz: 29ae4fb42d5d261b4e2a4d4e48e3a38f2d5a6282
3
+ metadata.gz: 13e8f04ebe8da4fdb6e846e27fff6e7818f8d603
4
+ data.tar.gz: 760267e338c5e9a374f375ce7f87ebca81e1d284
5
5
  SHA512:
6
- metadata.gz: fbb0d3e5004bdafdafffb4b9b6d72188f771e7976ef60d411bb394d30bc35cbe5c1fa059af2c1c09beea38ddee2642cd3400daf535a66ca7036fc28f6cd09c77
7
- data.tar.gz: f7d46b54a5e050e13d7f664ccb1f6034a89c45891b287d2ebfffebbc3aa2f16916d54b7be6d2cfa14d2cf3b642cb7dbc20aea742108f554ab7f8c6143bf005bb
6
+ metadata.gz: cadc65e83f29aadbe922cc61627a4eed560822480b61589f502808405312c56123415faaf4370a8932541b57c37cdc3d54483c260d836a19eba6c89fb32ea8a8
7
+ data.tar.gz: db8560beea1798a34a85d886393d8da833edf69a1973e55404ba5194e7013c2807734970f7636d0d764a72df3044c4fdb04999e80015058a6b069f56efa6f8d9
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # 0.0.5
2
+
3
+ * Fixed a bug that prevent to close lasts connections until get a new connection.
4
+ * Refactoring some code.
@@ -80,45 +80,31 @@ module CrapServer
80
80
  def start_ipv6_socket
81
81
  # :INET6 is to open an IPv6 connection
82
82
  # :STREAM is to open a TCP socket
83
- # After this line, the app is not yet ready to work, we only opened a socket
84
- socket_ipv6 = Socket.new(:INET6, :STREAM)
85
-
86
- begin
87
- # Now, bind the port.
88
- # ::1 is loopback for IPv6
89
- socket_ipv6.bind(Socket.pack_sockaddr_in(config.port, '::1'))
90
- rescue Errno::EADDRINUSE
91
- socket_ipv6.close
92
- raise ConnectionError.new "Unable to bind #{config.port} port."
93
- end
94
- socket_ipv6.listen(config.max_pending_connections)
95
- # Tell to the Kernel that is ok to rebind the port if is in TIME_WAIT state (after close the connection
96
- # and the Kernel wait for client acknowledgement)
97
- socket_ipv6.setsockopt(:SOCKET, :REUSEADDR, true)
98
-
99
- @socket6 = socket_ipv6
83
+ @socket6 = start_socket :INET6, :STREAM, '::1'
100
84
  end
101
85
 
102
86
  def start_ipv4_socket
103
- # :INET6 is to open an IPv6 connection
87
+ # :INET is to open an IPv4 connection
104
88
  # :STREAM is to open a TCP socket
105
- # After this line, the app is not yet ready to work, we only opened a socket
106
- socket_ipv4 = Socket.new(:INET, :STREAM)
89
+ @socket4 = start_socket :INET, :STREAM, '0.0.0.0'
90
+ end
91
+
92
+ def start_socket(version, type, loopback)
93
+ socket = Socket.new(version, type)
107
94
 
108
95
  begin
109
96
  # Now, bind the port.
110
- socket_ipv4.bind(Socket.pack_sockaddr_in(config.port, '0.0.0.0'))
97
+ socket.bind(Socket.pack_sockaddr_in(config.port, loopback))
111
98
  rescue Errno::EADDRINUSE
112
- socket_ipv4.close
99
+ socket.close
113
100
  raise ConnectionError.new "Unable to bind #{config.port} port."
114
101
  end
115
102
 
116
- socket_ipv4.listen(config.max_pending_connections)
103
+ socket.listen(config.max_pending_connections)
117
104
  # Tell to the Kernel that is ok to rebind the port if is in TIME_WAIT state (after close the connection
118
105
  # and the Kernel wait for client acknowledgement)
119
- socket_ipv4.setsockopt(:SOCKET, :REUSEADDR, true)
120
-
121
- @socket4 = socket_ipv4
106
+ socket.setsockopt(:SOCKET, :REUSEADDR, true)
107
+ socket
122
108
  end
123
109
 
124
110
  def socket_ipv6
@@ -101,61 +101,87 @@ module CrapServer
101
101
  protected
102
102
 
103
103
  # Evented loop (Reactor pattern)
104
- def accept_loop
104
+ def accept_loop(&block)
105
105
  loop {
106
+ logger.debug 'Start loop'
106
107
  @readables, @writables = IO.select(to_read, to_write)
107
108
 
108
- @readables.each do |socket|
109
- if @sockets.include? socket
110
- io, addr = socket.accept
111
- set_address io, addr
112
- set_close_after_write io if config.auto_close_connection
113
- # Disabling Nagle's algorithm. Is fucking slow :P
114
- io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
115
- # We add him to the read queue
116
- add_to_read io
117
- else
118
- begin
119
- _, data = socket, socket.read_nonblock(config.read_buffer_size)
120
- yield data, socket, address(socket)
121
- # We close the connection if we auto_close_connection is true and the user didn't write in the buffer.
122
- close socket if config.auto_close_connection && buffer(socket).nil?
123
- rescue Errno::EAGAIN
124
- rescue EOFError
125
- remove_to_read socket
126
- end
109
+ process_readables &block
110
+ process_writables
111
+ }
112
+ end
113
+
114
+ protected
115
+
116
+ def process_readables(&block)
117
+ @readables.each do |socket|
118
+ if @sockets.include? socket
119
+ accept_connection socket
120
+ else
121
+ begin
122
+ read_and_process_data socket, &block
123
+ rescue Errno::EAGAIN
124
+ rescue EOFError
125
+ remove_to_read socket
127
126
  end
128
127
  end
128
+ end
129
+ end
129
130
 
130
- @writables.each do |socket|
131
- begin
132
- string = buffer socket
133
- bytes = socket.write_nonblock string
134
- string.slice! 0, bytes
135
- if string.empty?
136
- # If we don't have more data to send to the client
137
- if close_after_write socket
138
- close socket
139
- else
140
- remove_to_write socket
141
- end
142
- else
143
- set_buffer socket, string
144
- remove_to_read socket
145
- end
146
- # If the client close the connection, we remove is from read and from write
147
- rescue Errno::ECONNRESET, Errno::EPIPE
131
+ def process_writables
132
+ @writables.each do |socket|
133
+ begin
134
+ string = buffer socket
135
+ bytes = socket.write_nonblock string
136
+ string.slice! 0, bytes
137
+ if string.empty?
138
+ # If we don't have more data to send to the client
148
139
  if close_after_write socket
149
140
  close socket
141
+ else
142
+ remove_to_write socket
150
143
  end
144
+ else
145
+ set_buffer socket, string
146
+ remove_to_read socket
147
+ end
148
+ # If the client close the connection, we remove is from read and from write
149
+ rescue Errno::ECONNRESET, Errno::EPIPE
150
+ if close_after_write socket
151
+ close socket
151
152
  end
152
153
  end
153
- }
154
+ end
155
+ end
156
+
157
+ def accept_connection(socket)
158
+ begin
159
+ io, addr = socket.accept_nonblock
160
+ set_address io, addr
161
+ set_close_after_write io if config.auto_close_connection
162
+ # Disabling Nagle's algorithm. Is fucking slow :P
163
+ io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
164
+ # We add him to the read queue
165
+ add_to_read io
166
+ rescue Errno::EINPROGRESS, IO::EAGAINWaitReadable
167
+ end
168
+ end
169
+
170
+ def read_and_process_data(socket, &block)
171
+ _, data = socket, socket.read_nonblock(config.read_buffer_size)
172
+ block.call data, socket, address(socket)
173
+ # We close the connection if we auto_close_connection is true and the user didn't write in the buffer.
174
+ if config.auto_close_connection && buffer(socket).nil?
175
+ close socket
176
+ end
154
177
  end
155
178
 
156
- protected
157
179
  def config
158
180
  CrapServer::Application.send(:config)
159
181
  end
182
+
183
+ def logger
184
+ CrapServer::Application.send(:logger)
185
+ end
160
186
  end
161
187
  end
@@ -41,7 +41,6 @@ module CrapServer
41
41
  def spawn_child
42
42
  fork do
43
43
  begin
44
-
45
44
  CrapServer::Application.send(:per_process_block).call if not CrapServer::Application.send(:per_process_block).nil?
46
45
  pool = CrapServer::ThreadPool.new @sockets
47
46
  pool.run &@block_proc
@@ -1,3 +1,3 @@
1
1
  module CrapServer
2
- VERSION = '0.0.4.2'
2
+ VERSION = '0.0.5.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crap_server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4.2
4
+ version: 0.0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andres Jose Borek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-08 00:00:00.000000000 Z
11
+ date: 2014-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -47,6 +47,7 @@ extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
49
  - ".gitignore"
50
+ - CHANGELOG.md
50
51
  - Gemfile
51
52
  - LICENSE.txt
52
53
  - README.md