serverengine 2.0.2-x86-mingw32 → 2.0.3-x86-mingw32

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: a7c0a5411c8ebe9d0a8ef19b0f6222dd279d5f28
4
- data.tar.gz: 84c3d6e12eb76f81a1768daafb5e78c9b355857d
3
+ metadata.gz: 30e143c93f13de994374897c12c6d5d8341121f6
4
+ data.tar.gz: 97e2987789826974472c8b7d2dfc26bb2a637d75
5
5
  SHA512:
6
- metadata.gz: 157e6c6fcce0b934d4af97565030b97012faac68c38a71b77aa8212bc1b86abbaa54fdd4152809b9760aa4201b58ab3b47d50a97f46a19ee1138b7364cc6af59
7
- data.tar.gz: 2479f98f06b7298cafc88b66f7c03829f07469f5bf8c02b5816c98aee9ec3be1df7950c3dfe8341bb08c10bc21be96a53fc671ec22861bec1faccc0dcd8222b0
6
+ metadata.gz: d338855b1925642c20a58ed8d73f4c05a7f160a0f18068b40f6370d595626d67914674988251a344fc2a3d6a86b4e4f57bfd2fff12be96cc6c6d26762f8fa0e7
7
+ data.tar.gz: e9808147809ce5f84e274f759bcef7c5d5105ea3e7d37484b8b64fe32a402c5c7bab500d254189157f307865f4a2596df0bc84037e0b95e11cb188241d97eed3
data/Changelog CHANGED
@@ -1,3 +1,7 @@
1
+ 2016-11-22 version 2.0.3:
2
+
3
+ * Fix bug about IPv6 handling on Windows
4
+
1
5
  2016-11-17 version 2.0.2:
2
6
 
3
7
  * Fix bug to make busy loop on Windows
@@ -26,34 +26,36 @@ module ServerEngine
26
26
  @path = path
27
27
  end
28
28
 
29
- def listen_tcp(bind, port)
29
+ def listen(proto, bind, port)
30
+ bind_ip = IPAddr.new(IPSocket.getaddress(bind))
31
+ family = bind_ip.ipv6? ? Socket::AF_INET6 : Socket::AF_INET
32
+
33
+ listen_method = case proto
34
+ when :tcp then :listen_tcp
35
+ when :udp then :listen_udp
36
+ else
37
+ raise ArgumentError, "unknown protocol: #{proto}"
38
+ end
30
39
  peer = connect_peer(@path)
31
40
  begin
32
- SocketManager.send_peer(peer, [Process.pid, :listen_tcp, bind, port])
41
+ SocketManager.send_peer(peer, [Process.pid, listen_method, bind, port])
33
42
  res = SocketManager.recv_peer(peer)
34
43
  if res.is_a?(Exception)
35
44
  raise res
36
45
  else
37
- return recv_tcp(peer, res)
46
+ return send(:recv, family, proto, peer, res)
38
47
  end
39
48
  ensure
40
49
  peer.close
41
50
  end
42
51
  end
43
52
 
53
+ def listen_tcp(bind, port)
54
+ listen(:tcp, bind, port)
55
+ end
56
+
44
57
  def listen_udp(bind, port)
45
- peer = connect_peer(@path)
46
- begin
47
- SocketManager.send_peer(peer, [Process.pid, :listen_udp, bind, port])
48
- res = SocketManager.recv_peer(peer)
49
- if res.is_a?(Exception)
50
- raise res
51
- else
52
- return recv_udp(peer, res)
53
- end
54
- ensure
55
- peer.close
56
- end
58
+ listen(:udp, bind, port)
57
59
  end
58
60
  end
59
61
 
@@ -94,28 +96,29 @@ module ServerEngine
94
96
 
95
97
  private
96
98
 
97
- def listen_tcp(bind, port)
99
+ def listen(proto, bind, port)
100
+ sockets, new_method = case proto
101
+ when :tcp then [@tcp_sockets, :listen_tcp_new]
102
+ when :udp then [@udp_sockets, :listen_udp_new]
103
+ else
104
+ raise ArgumentError, "invalid protocol: #{proto}"
105
+ end
98
106
  key, bind_ip = resolve_bind_key(bind, port)
99
107
 
100
108
  @mutex.synchronize do
101
- if @tcp_sockets.has_key?(key)
102
- return @tcp_sockets[key]
103
- else
104
- return @tcp_sockets[key] = listen_tcp_new(bind_ip, port)
109
+ unless sockets.has_key?(key)
110
+ sockets[key] = send(new_method, bind_ip, port)
105
111
  end
112
+ return sockets[key]
106
113
  end
107
114
  end
108
115
 
109
- def listen_udp(bind, port)
110
- key, bind_ip = resolve_bind_key(bind, port)
116
+ def listen_tcp(bind, port)
117
+ listen(:tcp, bind, port)
118
+ end
111
119
 
112
- @mutex.synchronize do
113
- if @udp_sockets.has_key?(key)
114
- return @udp_sockets[key]
115
- else
116
- return @udp_sockets[key] = listen_udp_new(bind_ip, port)
117
- end
118
- end
120
+ def listen_udp(bind, port)
121
+ listen(:udp, bind, port)
119
122
  end
120
123
 
121
124
  def resolve_bind_key(bind, port)
@@ -27,12 +27,22 @@ module ServerEngine
27
27
  return UNIXSocket.new(path)
28
28
  end
29
29
 
30
- def recv_tcp(peer, sent)
31
- return peer.recv_io(TCPServer)
30
+ def recv(family, proto, peer, sent)
31
+ server_class = case proto
32
+ when :tcp then TCPServer
33
+ when :udp then UDPSocket
34
+ else
35
+ raise ArgumentError, "invalid protocol: #{proto}"
36
+ end
37
+ peer.recv_io(server_class)
32
38
  end
33
39
 
34
- def recv_udp(peer, sent)
35
- return peer.recv_io(UDPSocket)
40
+ def recv_tcp(family, peer, sent)
41
+ recv(family, :tcp, peer, sent)
42
+ end
43
+
44
+ def recv_udp(family, peer, sent)
45
+ recv(family, :udp, peer, sent)
36
46
  end
37
47
  end
38
48
 
@@ -49,7 +59,7 @@ module ServerEngine
49
59
  if bind_ip.ipv6?
50
60
  sock = UDPSocket.new(Socket::AF_INET6)
51
61
  else
52
- sock = UDPSocket.new
62
+ sock = UDPSocket.new(Socket::AF_INET)
53
63
  end
54
64
  sock.bind(bind_ip.to_s, port)
55
65
  return sock
@@ -30,74 +30,77 @@ module ServerEngine
30
30
  return TCPSocket.open("127.0.0.1", addr)
31
31
  end
32
32
 
33
- def recv_tcp(peer, sent)
34
- proto = WinSock::WSAPROTOCOL_INFO.from_bin(sent)
33
+ def recv(family, proto, peer, sent)
34
+ server_class, protocol = case proto
35
+ when :tcp then [TCPServer, Socket::SOCK_STREAM]
36
+ when :udp then [UDPSocket, Socket::SOCK_DGRAM]
37
+ else
38
+ raise ArgumentError, "invalid protocol: #{proto}"
39
+ end
35
40
 
36
- handle = WinSock.WSASocketA(Socket::AF_INET, Socket::SOCK_STREAM, 0, proto, 0, 1)
41
+ proto_info = WinSock::WSAPROTOCOL_INFO.from_bin(sent)
42
+
43
+ handle = WinSock.WSASocketA(family, protocol, 0, proto_info, 0, 1)
37
44
  if handle == WinSock::INVALID_SOCKET
38
45
  RbWinSock.raise_last_error("WSASocketA(2)")
39
46
  end
40
47
 
41
- return RbWinSock.wrap_io_handle(TCPServer, handle, 0)
48
+ return RbWinSock.wrap_io_handle(server_class, handle, 0)
42
49
  end
43
50
 
44
- def recv_udp(peer, sent)
45
- proto = WinSock::WSAPROTOCOL_INFO.from_bin(sent)
46
-
47
- handle = WinSock.WSASocketA(Socket::AF_INET, Socket::SOCK_DGRAM, 0, proto, 0, 1)
48
- if handle == WinSock::INVALID_SOCKET
49
- RbWinSock.raise_last_error("WSASocketA(2)")
50
- end
51
+ def recv_tcp(family, peer, sent)
52
+ recv(family, :tcp, peer, sent)
53
+ end
51
54
 
52
- return RbWinSock.wrap_io_handle(UDPSocket, handle, 0)
55
+ def recv_udp(family, peer, sent)
56
+ recv(family, :udp, peer, sent)
53
57
  end
54
58
  end
55
59
 
56
60
  module ServerModule
57
61
  private
58
62
 
59
- def listen_tcp_new(bind_ip, port)
63
+ TCP_OPTIONS = [Socket::SOCK_STREAM, Socket::IPPROTO_TCP, TCPServer, true]
64
+ UDP_OPTIONS = [Socket::SOCK_DGRAM, Socket::IPPROTO_UDP, UDPSocket, false]
65
+
66
+ def listen_new(proto, bind_ip, port)
67
+ protocol, proto_info, klass, listen = case proto
68
+ when :tcp then TCP_OPTIONS
69
+ when :udp then UDP_OPTIONS
70
+ else
71
+ raise ArgumentError, "invalid protocol: #{proto}"
72
+ end
73
+ family = bind_ip.ipv6? ? Socket::AF_INET6 : Socket::AF_INET
74
+
60
75
  sock_addr = Socket.pack_sockaddr_in(port, bind_ip.to_s)
61
76
 
62
- handle = WinSock.WSASocketA(Socket::AF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP, nil, 0, 1)
77
+ handle = WinSock.WSASocketA(family, protocol, proto_info, nil, 0, 1)
63
78
  if handle == WinSock::INVALID_SOCKET
64
79
  RbWinSock.raise_last_error("WSASocketA(2)")
65
80
  end
66
81
 
67
- # wrap in TCPServer immediately so that its finalizer safely closes the handle
68
- sock = RbWinSock.wrap_io_handle(TCPServer, handle, 0)
82
+ # wrap in TCPServer/UDPSocket immediately so that its finalizer safely closes the handle
83
+ sock = RbWinSock.wrap_io_handle(klass, handle, 0)
69
84
 
70
85
  unless WinSock.bind(sock.handle, sock_addr, sock_addr.bytesize) == 0
71
86
  RbWinSock.raise_last_error("bind(2)")
72
87
  end
73
- unless WinSock.listen(sock.handle, Socket::SOMAXCONN) == 0
74
- RbWinSock.raise_last_error("listen(2)")
75
- end
76
-
77
- return sock
78
- end
79
-
80
- def listen_udp_new(bind_ip, port)
81
- sock_addr = Socket.pack_sockaddr_in(port, bind_ip.to_s)
82
-
83
- if IPAddr.new(IPSocket.getaddress(bind_ip.to_s)).ipv4?
84
- handle = WinSock.WSASocketA(Socket::AF_INET, Socket::SOCK_DGRAM, Socket::IPPROTO_UDP, nil, 0, 1)
85
- else
86
- handle = WinSock.WSASocketA(Socket::AF_INET6, Socket::SOCK_DGRAM, Socket::IPPROTO_UDP, nil, 0, 1)
87
- end
88
88
 
89
- if handle == WinSock::INVALID_SOCKET
90
- RbWinSock.raise_last_error("WSASocketA(2)")
89
+ if listen
90
+ unless WinSock.listen(sock.handle, Socket::SOMAXCONN) == 0
91
+ RbWinSock.raise_last_error("listen(2)")
92
+ end
91
93
  end
92
94
 
93
- # wrap in UDPSocket immediately so that its finalizer safely closes the handle
94
- sock = RbWinSock.wrap_io_handle(UDPSocket, handle, 0)
95
+ sock
96
+ end
95
97
 
96
- unless WinSock.bind(sock.handle, sock_addr, sock_addr.bytesize) == 0
97
- RbWinSock.raise_last_error("bind(2)")
98
- end
98
+ def listen_tcp_new(bind_ip, port)
99
+ listen_new(:tcp, bind_ip, port)
100
+ end
99
101
 
100
- return sock
102
+ def listen_udp_new(bind_ip, port)
103
+ listen_new(:udp, bind_ip, port)
101
104
  end
102
105
 
103
106
  def htons(h)
@@ -1,3 +1,3 @@
1
1
  module ServerEngine
2
- VERSION = "2.0.2"
2
+ VERSION = "2.0.3"
3
3
  end
@@ -1,57 +1,134 @@
1
+ require 'socket'
1
2
 
2
3
  describe ServerEngine::SocketManager do
3
4
  include_context 'test server and worker'
4
5
 
5
6
  let(:server_path) do
6
- 'tmp/socket_manager_test.sock'
7
+ if ServerEngine.windows?
8
+ 24223
9
+ else
10
+ 'tmp/socket_manager_test.sock'
11
+ end
12
+ end
13
+
14
+ let(:test_port) do
15
+ 9101
7
16
  end
8
17
 
9
18
  after(:each) do
10
- File.unlink(server_path) if File.exist?(server_path)
19
+ File.unlink(server_path) if server_path.is_a?(String) && File.exist?(server_path)
11
20
  end
12
21
 
13
- if ServerEngine.windows?
14
- let(:server_port) do
15
- 24223
16
- end
22
+ context 'with thread' do
23
+ context 'using ipv4' do
24
+ it 'works' do
25
+ server = SocketManager::Server.open(server_path)
17
26
 
18
- let(:test_port) do
19
- 9101
20
- end
27
+ mutex = Mutex.new
28
+ server_thread_started = false
21
29
 
22
- it 'is windows' do
23
- SocketManager::Client.is_a?(SocketManagerWin::ClientModule)
24
- SocketManager::Server.is_a?(SocketManagerWin::ServerModule)
25
- end
30
+ thread = Thread.new do
31
+ mutex.lock
32
+ server_thread_started = true
33
+
34
+ begin
35
+ client = ServerEngine::SocketManager::Client.new(server_path)
36
+
37
+ tcp = client.listen_tcp('127.0.0.1', test_port)
38
+ udp = client.listen_udp('127.0.0.1', test_port)
39
+
40
+ incr_test_state(:is_tcp_server) if tcp.is_a?(TCPServer)
41
+ incr_test_state(:is_udp_socket) if udp.is_a?(UDPSocket)
42
+
43
+ mutex.unlock
44
+
45
+ data, _from = udp.recvfrom(10)
46
+ incr_test_state(:udp_data_sent) if data == "ok"
47
+
48
+ s = tcp.accept
49
+ s.write("ok")
50
+ s.close
51
+ rescue => e
52
+ p(here: "rescue in server thread", error: e)
53
+ e.backtrace.each do |bt|
54
+ STDERR.puts bt
55
+ end
56
+ raise
57
+ ensure
58
+ tcp.close
59
+ udp.close
60
+ end
61
+ end
26
62
 
27
- context 'with thread' do
28
- it 'works' do
29
- server = SocketManager::Server.open(server_port)
63
+ sleep 0.1 until server_thread_started
64
+ sleep 0.1 while mutex.locked?
30
65
 
31
- thread = Thread.new do
66
+ u = UDPSocket.new(Socket::AF_INET)
67
+ u.send "ok", 0, '127.0.0.1', test_port
68
+ u.close
32
69
 
33
- client = ServerEngine::SocketManager::Client.new(server_port)
34
- tcp = client.listen_tcp('127.0.0.1', test_port)
35
- udp = client.listen_udp('127.0.0.1', test_port)
70
+ t = TCPSocket.open('127.0.0.1', test_port)
71
+ t.read.should == "ok"
72
+ t.close
36
73
 
37
- incr_test_state(:is_tcp_server) if tcp.is_a?(TCPServer)
38
- incr_test_state(:is_udp_socket) if udp.is_a?(UDPSocket)
74
+ server.close
75
+ thread.join
39
76
 
40
- data, _from = udp.recvfrom(10)
41
- incr_test_state(:udp_data_sent) if data == "ok"
77
+ test_state(:is_tcp_server).should == 1
78
+ test_state(:is_udp_socket).should == 1
79
+ test_state(:udp_data_sent).should == 1
80
+ end
81
+ end
42
82
 
43
- s = tcp.accept
44
- s.write("ok")
45
- s.close
83
+ context 'using ipv6' do
84
+ it 'works' do
85
+ server = SocketManager::Server.open(server_path)
86
+
87
+ mutex = Mutex.new
88
+ server_thread_started = false
89
+
90
+ thread = Thread.new do
91
+ Thread.current.abort_on_exception = true
92
+ mutex.lock
93
+ server_thread_started = true
94
+
95
+ begin
96
+ client = ServerEngine::SocketManager::Client.new(server_path)
97
+
98
+ tcp = client.listen_tcp('::1', test_port)
99
+ udp = client.listen_udp('::1', test_port)
100
+
101
+ incr_test_state(:is_tcp_server) if tcp.is_a?(TCPServer)
102
+ incr_test_state(:is_udp_socket) if udp.is_a?(UDPSocket)
103
+
104
+ mutex.unlock
105
+
106
+ data, _from = udp.recvfrom(10)
107
+ incr_test_state(:udp_data_sent) if data == "ok"
108
+
109
+ s = tcp.accept
110
+ s.write("ok")
111
+ s.close
112
+ rescue => e
113
+ p(here: "rescue in server thread", error: e)
114
+ e.backtrace.each do |bt|
115
+ STDERR.puts bt
116
+ end
117
+ raise
118
+ ensure
119
+ tcp.close
120
+ udp.close
121
+ end
46
122
  end
47
123
 
48
- sleep 1
124
+ sleep 0.1 until server_thread_started
125
+ sleep 0.1 while mutex.locked?
49
126
 
50
- u = UDPSocket.new
51
- u.send "ok", 0, '127.0.0.1', test_port
127
+ u = UDPSocket.new(Socket::AF_INET6)
128
+ u.send "ok", 0, '::1', test_port
52
129
  u.close
53
130
 
54
- t = TCPSocket.open('127.0.0.1', test_port)
131
+ t = TCPSocket.open('::1', test_port)
55
132
  t.read.should == "ok"
56
133
  t.close
57
134
 
@@ -62,13 +139,15 @@ describe ServerEngine::SocketManager do
62
139
  test_state(:is_udp_socket).should == 1
63
140
  test_state(:udp_data_sent).should == 1
64
141
  end
65
- end
142
+ end if (TCPServer.open("::1",0) rescue nil)
143
+ end
66
144
 
67
- else
68
- let(:test_port) do
69
- 9102
145
+ if ServerEngine.windows?
146
+ it 'is windows' do
147
+ SocketManager::Client.is_a?(SocketManagerWin::ClientModule)
148
+ SocketManager::Server.is_a?(SocketManagerWin::ServerModule)
70
149
  end
71
-
150
+ else
72
151
  it 'is unix' do
73
152
  SocketManager::Client.is_a?(SocketManagerUnix::ClientModule)
74
153
  SocketManager::Server.is_a?(SocketManagerUnix::ServerModule)
@@ -81,20 +160,25 @@ describe ServerEngine::SocketManager do
81
160
  fork do
82
161
  server.close
83
162
 
84
- client = server.new_client
163
+ begin
164
+ client = server.new_client
85
165
 
86
- tcp = client.listen_tcp('127.0.0.1', test_port)
87
- udp = client.listen_udp('127.0.0.1', test_port)
166
+ tcp = client.listen_tcp('127.0.0.1', test_port)
167
+ udp = client.listen_udp('127.0.0.1', test_port)
88
168
 
89
- incr_test_state(:is_tcp_server) if tcp.is_a?(TCPServer)
90
- incr_test_state(:is_udp_socket) if udp.is_a?(UDPSocket)
169
+ incr_test_state(:is_tcp_server) if tcp.is_a?(TCPServer)
170
+ incr_test_state(:is_udp_socket) if udp.is_a?(UDPSocket)
91
171
 
92
- data, _from = udp.recvfrom(10)
93
- incr_test_state(:udp_data_sent) if data == "ok"
172
+ data, _from = udp.recvfrom(10)
173
+ incr_test_state(:udp_data_sent) if data == "ok"
94
174
 
95
- s = tcp.accept
96
- s.write("ok")
97
- s.close
175
+ s = tcp.accept
176
+ s.write("ok")
177
+ s.close
178
+ ensure
179
+ tcp.close
180
+ udp.close
181
+ end
98
182
  end
99
183
 
100
184
  wait_for_fork
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serverengine
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.0.3
5
5
  platform: x86-mingw32
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-17 00:00:00.000000000 Z
11
+ date: 2016-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sigdump