rubysl-socket 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +0 -1
  3. data/.travis.yml +7 -0
  4. data/README.md +2 -2
  5. data/Rakefile +0 -1
  6. data/lib/rubysl/socket.rb +2 -0
  7. data/lib/rubysl/socket/socket.rb +1210 -0
  8. data/lib/{rubysl-socket → rubysl/socket}/version.rb +1 -1
  9. data/lib/socket.rb +1 -0
  10. data/rubysl-socket.gemspec +17 -18
  11. data/spec/addrinfo/afamily_spec.rb +5 -0
  12. data/spec/addrinfo/bind_spec.rb +5 -0
  13. data/spec/addrinfo/canonname_spec.rb +5 -0
  14. data/spec/addrinfo/connect_from_spec.rb +5 -0
  15. data/spec/addrinfo/connect_spec.rb +5 -0
  16. data/spec/addrinfo/connect_to_spec.rb +5 -0
  17. data/spec/addrinfo/family_addrinfo_spec.rb +5 -0
  18. data/spec/addrinfo/foreach_spec.rb +5 -0
  19. data/spec/addrinfo/getaddrinfo_spec.rb +5 -0
  20. data/spec/addrinfo/getnameinfo_spec.rb +5 -0
  21. data/spec/addrinfo/inspect_sockaddr_spec.rb +5 -0
  22. data/spec/addrinfo/inspect_spec.rb +5 -0
  23. data/spec/addrinfo/ip_address_spec.rb +5 -0
  24. data/spec/addrinfo/ip_port_spec.rb +5 -0
  25. data/spec/addrinfo/ip_spec.rb +9 -0
  26. data/spec/addrinfo/ip_unpack_spec.rb +5 -0
  27. data/spec/addrinfo/ipv4_loopback_spec.rb +5 -0
  28. data/spec/addrinfo/ipv4_multicast_spec.rb +5 -0
  29. data/spec/addrinfo/ipv4_private_spec.rb +5 -0
  30. data/spec/addrinfo/ipv4_spec.rb +5 -0
  31. data/spec/addrinfo/ipv6_linklocal_spec.rb +5 -0
  32. data/spec/addrinfo/ipv6_loopback_spec.rb +5 -0
  33. data/spec/addrinfo/ipv6_mc_global_spec.rb +5 -0
  34. data/spec/addrinfo/ipv6_mc_linklocal_spec.rb +5 -0
  35. data/spec/addrinfo/ipv6_mc_nodelocal_spec.rb +5 -0
  36. data/spec/addrinfo/ipv6_mc_orglocal_spec.rb +5 -0
  37. data/spec/addrinfo/ipv6_mc_sitelocal_spec.rb +5 -0
  38. data/spec/addrinfo/ipv6_multicast_spec.rb +5 -0
  39. data/spec/addrinfo/ipv6_sitelocal_spec.rb +5 -0
  40. data/spec/addrinfo/ipv6_spec.rb +5 -0
  41. data/spec/addrinfo/ipv6_to_ipv4_spec.rb +5 -0
  42. data/spec/addrinfo/ipv6_unspecified_spec.rb +5 -0
  43. data/spec/addrinfo/ipv6_v4compat_spec.rb +5 -0
  44. data/spec/addrinfo/ipv6_v4mapped_spec.rb +5 -0
  45. data/spec/addrinfo/listen_spec.rb +5 -0
  46. data/spec/addrinfo/marshal_dump_spec.rb +5 -0
  47. data/spec/addrinfo/marshal_load_spec.rb +5 -0
  48. data/spec/addrinfo/pfamily_spec.rb +5 -0
  49. data/spec/addrinfo/protocol_spec.rb +5 -0
  50. data/spec/addrinfo/socktype_spec.rb +5 -0
  51. data/spec/addrinfo/tcp_spec.rb +5 -0
  52. data/spec/addrinfo/to_s_spec.rb +5 -0
  53. data/spec/addrinfo/to_sockaddr_spec.rb +5 -0
  54. data/spec/addrinfo/udp_spec.rb +5 -0
  55. data/spec/addrinfo/unix_path_spec.rb +5 -0
  56. data/spec/addrinfo/unix_spec.rb +9 -0
  57. data/spec/basicsocket/close_read_spec.rb +42 -0
  58. data/spec/basicsocket/close_write_spec.rb +42 -0
  59. data/spec/basicsocket/do_not_reverse_lookup_spec.rb +78 -0
  60. data/spec/basicsocket/for_fd_spec.rb +37 -0
  61. data/spec/basicsocket/getpeername_spec.rb +24 -0
  62. data/spec/basicsocket/getsockname_spec.rb +27 -0
  63. data/spec/basicsocket/getsockopt_spec.rb +54 -0
  64. data/spec/basicsocket/ioctl_spec.rb +22 -0
  65. data/spec/basicsocket/recv_nonblock_spec.rb +6 -0
  66. data/spec/basicsocket/recv_spec.rb +76 -0
  67. data/spec/basicsocket/send_spec.rb +81 -0
  68. data/spec/basicsocket/setsockopt_spec.rb +333 -0
  69. data/spec/basicsocket/shutdown_spec.rb +5 -0
  70. data/spec/constants/constants_spec.rb +63 -0
  71. data/spec/fixtures/classes.rb +174 -0
  72. data/spec/fixtures/send_io.txt +1 -0
  73. data/spec/ipsocket/addr_spec.rb +72 -0
  74. data/spec/ipsocket/getaddress_spec.rb +26 -0
  75. data/spec/ipsocket/peeraddr_spec.rb +79 -0
  76. data/spec/ipsocket/recvfrom_spec.rb +64 -0
  77. data/spec/option/int_spec.rb +27 -0
  78. data/spec/option/linger_spec.rb +52 -0
  79. data/spec/option/new_spec.rb +32 -0
  80. data/spec/shared/pack_sockaddr.rb +26 -0
  81. data/spec/shared/partially_closable_sockets.rb +13 -0
  82. data/spec/shared/recv_nonblock.rb +33 -0
  83. data/spec/shared/socketpair.rb +35 -0
  84. data/spec/socket/accept_nonblock_spec.rb +27 -0
  85. data/spec/socket/accept_spec.rb +1 -0
  86. data/spec/socket/bind_spec.rb +80 -0
  87. data/spec/socket/connect_nonblock_spec.rb +62 -0
  88. data/spec/socket/connect_spec.rb +1 -0
  89. data/spec/socket/for_fd_spec.rb +29 -0
  90. data/spec/socket/getaddrinfo_spec.rb +120 -0
  91. data/spec/socket/gethostbyaddr_spec.rb +1 -0
  92. data/spec/socket/gethostbyname_spec.rb +26 -0
  93. data/spec/socket/gethostname_spec.rb +9 -0
  94. data/spec/socket/getnameinfo_spec.rb +57 -0
  95. data/spec/socket/getservbyname_spec.rb +24 -0
  96. data/spec/socket/listen_spec.rb +21 -0
  97. data/spec/socket/new_spec.rb +109 -0
  98. data/spec/socket/pack_sockaddr_in_spec.rb +6 -0
  99. data/spec/socket/pack_sockaddr_un_spec.rb +6 -0
  100. data/spec/socket/pair_spec.rb +6 -0
  101. data/spec/socket/recvfrom_nonblock_spec.rb +1 -0
  102. data/spec/socket/recvfrom_spec.rb +1 -0
  103. data/spec/socket/sockaddr_in_spec.rb +6 -0
  104. data/spec/socket/sockaddr_un_spec.rb +6 -0
  105. data/spec/socket/socket_spec.rb +37 -0
  106. data/spec/socket/socketpair_spec.rb +6 -0
  107. data/spec/socket/sysaccept_spec.rb +1 -0
  108. data/spec/socket/unpack_sockaddr_in_spec.rb +16 -0
  109. data/spec/socket/unpack_sockaddr_un_spec.rb +2 -0
  110. data/spec/tcpserver/accept_nonblock_spec.rb +30 -0
  111. data/spec/tcpserver/accept_spec.rb +60 -0
  112. data/spec/tcpserver/gets_spec.rb +17 -0
  113. data/spec/tcpserver/listen_spec.rb +1 -0
  114. data/spec/tcpserver/new_spec.rb +88 -0
  115. data/spec/tcpserver/output_spec.rb +8 -0
  116. data/spec/tcpserver/readpartial_spec.rb +8 -0
  117. data/spec/tcpserver/sysaccept_spec.rb +1 -0
  118. data/spec/tcpsocket/gethostbyname_spec.rb +62 -0
  119. data/spec/tcpsocket/new_spec.rb +5 -0
  120. data/spec/tcpsocket/open_spec.rb +5 -0
  121. data/spec/tcpsocket/partially_closable_spec.rb +20 -0
  122. data/spec/tcpsocket/recv_nonblock_spec.rb +31 -0
  123. data/spec/tcpsocket/setsockopt_spec.rb +49 -0
  124. data/spec/tcpsocket/shared/new.rb +85 -0
  125. data/spec/udpsocket/bind_spec.rb +33 -0
  126. data/spec/udpsocket/connect_spec.rb +1 -0
  127. data/spec/udpsocket/new_spec.rb +1 -0
  128. data/spec/udpsocket/open_spec.rb +12 -0
  129. data/spec/udpsocket/recvfrom_nonblock_spec.rb +1 -0
  130. data/spec/udpsocket/send_spec.rb +57 -0
  131. data/spec/unixserver/accept_nonblock_spec.rb +33 -0
  132. data/spec/unixserver/accept_spec.rb +64 -0
  133. data/spec/unixserver/for_fd_spec.rb +32 -0
  134. data/spec/unixserver/new_spec.rb +5 -0
  135. data/spec/unixserver/open_spec.rb +25 -0
  136. data/spec/unixserver/shared/new.rb +23 -0
  137. data/spec/unixsocket/addr_spec.rb +37 -0
  138. data/spec/unixsocket/new_spec.rb +5 -0
  139. data/spec/unixsocket/open_spec.rb +26 -0
  140. data/spec/unixsocket/pair_spec.rb +38 -0
  141. data/spec/unixsocket/partially_closable_spec.rb +25 -0
  142. data/spec/unixsocket/path_spec.rb +29 -0
  143. data/spec/unixsocket/peeraddr_spec.rb +29 -0
  144. data/spec/unixsocket/recv_io_spec.rb +40 -0
  145. data/spec/unixsocket/recvfrom_spec.rb +48 -0
  146. data/spec/unixsocket/send_io_spec.rb +30 -0
  147. data/spec/unixsocket/shared/new.rb +25 -0
  148. metadata +328 -89
  149. data/lib/rubysl-socket.rb +0 -7
@@ -0,0 +1,78 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ ruby_version_is ""..."1.9" do
4
+ describe "BasicSocket.do_not_reverse_lookup" do
5
+ before :all do
6
+ @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
7
+ end
8
+
9
+ before(:each) do
10
+ @server = TCPServer.new('127.0.0.1', SocketSpecs.port)
11
+ @socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
12
+ end
13
+
14
+ after(:each) do
15
+ @socket.close unless @socket.closed?
16
+ @server.close unless @server.closed?
17
+ end
18
+
19
+ after :all do
20
+ BasicSocket.do_not_reverse_lookup = @do_not_reverse_lookup
21
+ end
22
+
23
+ it "defaults to false" do
24
+ BasicSocket.do_not_reverse_lookup.should be_false
25
+ end
26
+
27
+ it "causes 'peeraddr' to avoid name lookups" do
28
+ BasicSocket.do_not_reverse_lookup = true
29
+ @socket.peeraddr.should == ["AF_INET", SocketSpecs.port, "127.0.0.1", "127.0.0.1"]
30
+ end
31
+
32
+ it "looks for hostnames when set to false" do
33
+ BasicSocket.do_not_reverse_lookup = false
34
+ @socket.peeraddr[2].should == SocketSpecs.hostname
35
+ end
36
+
37
+ it "looks for numeric addresses when set to true" do
38
+ BasicSocket.do_not_reverse_lookup = true
39
+ @socket.peeraddr[2].should == "127.0.0.1"
40
+ end
41
+ end
42
+ end
43
+
44
+ ruby_version_is "1.9" do
45
+ describe "BasicSocket.do_not_reverse_lookup" do
46
+ before(:each) do
47
+ @server = TCPServer.new('127.0.0.1', SocketSpecs.port)
48
+ @socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
49
+ end
50
+
51
+ after(:each) do
52
+ @server.close unless @server.closed?
53
+ @socket.close unless @socket.closed?
54
+ end
55
+
56
+ it "defaults to true" do
57
+ BasicSocket.do_not_reverse_lookup.should be_true
58
+ end
59
+
60
+ it "causes 'peeraddr' to avoid name lookups" do
61
+ @socket.do_not_reverse_lookup = true
62
+ BasicSocket.do_not_reverse_lookup = true
63
+ @socket.peeraddr.should == ["AF_INET", SocketSpecs.port, "127.0.0.1", "127.0.0.1"]
64
+ end
65
+
66
+ it "looks for hostnames when set to false" do
67
+ @socket.do_not_reverse_lookup = false
68
+ BasicSocket.do_not_reverse_lookup = false
69
+ @socket.peeraddr[2].should == SocketSpecs.hostname
70
+ end
71
+
72
+ it "looks for numeric addresses when set to true" do
73
+ @socket.do_not_reverse_lookup = true
74
+ BasicSocket.do_not_reverse_lookup = true
75
+ @socket.peeraddr[2].should == "127.0.0.1"
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,37 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ describe "BasicSocket#for_fd" do
4
+ before :each do
5
+ @server = TCPServer.new(SocketSpecs.port)
6
+ @s2 = nil
7
+ end
8
+
9
+ after :each do
10
+ # UG. We can't use the new_fd helper, because we need fds that are
11
+ # associated with sockets. But for_fd has the same issue as IO#new, it
12
+ # creates a fd aliasing issue with closing, causing EBADF errors.
13
+ #
14
+ # Thusly, the rescue for EBADF here. I'd love a better solution, but
15
+ # I'm not aware of one.
16
+
17
+ begin
18
+ @server.close unless @server.closed?
19
+ rescue Errno::EBADF
20
+ # I hate this API
21
+ end
22
+
23
+ begin
24
+ if @s2
25
+ @s2.close unless @s2.closed?
26
+ end
27
+ rescue Errno::EBADF
28
+ # I hate this API
29
+ end
30
+ end
31
+
32
+ it "return a Socket instance wrapped around the descriptor" do
33
+ @s2 = TCPServer.for_fd(@server.fileno)
34
+ @s2.should be_kind_of(TCPServer)
35
+ @s2.fileno.should == @server.fileno
36
+ end
37
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ describe "Socket::BasicSocket#getpeername" do
4
+
5
+ before :each do
6
+ @server = TCPServer.new("127.0.0.1", SocketSpecs.port)
7
+ @client = TCPSocket.new("127.0.0.1", SocketSpecs.port)
8
+ end
9
+
10
+ after :each do
11
+ @server.close unless @server.closed?
12
+ @client.close unless @client.closed?
13
+ end
14
+
15
+ it "returns the sockaddr of the other end of the connection" do
16
+ server_sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1")
17
+ @client.getpeername.should == server_sockaddr
18
+ end
19
+
20
+ # Catch general exceptions to prevent NotImplementedError
21
+ it "raises an error if socket's not connected" do
22
+ lambda { @server.getpeername }.should raise_error(Exception)
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ describe "Socket::BasicSocket#getsockname" do
4
+ after :each do
5
+ @socket.closed?.should be_false
6
+ @socket.close
7
+ end
8
+
9
+ it "returns the sockaddr associacted with the socket" do
10
+ @socket = TCPServer.new("127.0.0.1", SocketSpecs.port)
11
+ sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
12
+ sockaddr.should == [SocketSpecs.port, "127.0.0.1"]
13
+ end
14
+
15
+ it "works on sockets listening in ipaddr_any" do
16
+ @socket = TCPServer.new(SocketSpecs.port)
17
+ sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
18
+ ["::", "0.0.0.0", "::ffff:0.0.0.0"].include?(sockaddr[1]).should be_true
19
+ sockaddr[0].should == SocketSpecs.port
20
+ end
21
+
22
+ it "returns empty sockaddr for unbinded sockets" do
23
+ @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
24
+ sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
25
+ sockaddr.should == [0, "0.0.0.0"]
26
+ end
27
+ end
@@ -0,0 +1,54 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ describe "BasicSocket#getsockopt" do
4
+ before(:each) do
5
+ @sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
6
+ end
7
+
8
+ after :each do
9
+ @sock.closed?.should be_false
10
+ @sock.close
11
+ end
12
+
13
+ it "gets a socket option Socket::SO_TYPE" do
14
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE).to_s
15
+ n.should == [Socket::SOCK_STREAM].pack("i")
16
+ end
17
+
18
+ it "gets a socket option Socket::SO_OOBINLINE" do
19
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
20
+ n.should == [0].pack("i")
21
+ end
22
+
23
+ it "gets a socket option Socket::SO_LINGER" do
24
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
25
+ if (n.size == 8) # linger struct on some platforms, not just a value
26
+ n.should == [0, 0].pack("ii")
27
+ else
28
+ n.should == [0].pack("i")
29
+ end
30
+ end
31
+
32
+ it "gets a socket option Socket::SO_SNDBUF" do
33
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
34
+ n.unpack('i')[0].should > 0
35
+ end
36
+
37
+ it "raises a SystemCallError with an invalid socket option" do
38
+ lambda { @sock.getsockopt Socket::SOL_SOCKET, -1 }.should raise_error(Errno::ENOPROTOOPT)
39
+ end
40
+
41
+ ruby_version_is "1.9.2" do
42
+ it "gets a Socket::Option" do
43
+ so = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE)
44
+ so.class.should == Socket::Option
45
+ so.level.should == Socket::SOL_SOCKET
46
+ so.optname.should == Socket::SO_TYPE
47
+ so.int.should == Socket::SOCK_STREAM
48
+
49
+ so = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
50
+ so.optname.should == Socket::SO_LINGER
51
+ so.linger.should == [false, 0]
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,22 @@
1
+ require 'socket'
2
+
3
+ describe "Socket::BasicSocket#ioctl" do
4
+ platform_is :os => :linux do
5
+ it "passes data from and to a String correctly" do
6
+ s = Socket.new Socket::AF_INET, Socket::SOCK_DGRAM, 0
7
+ # /usr/include/net/if.h, structure ifreq
8
+ # The structure is 32 bytes on x86, 40 bytes on x86_64
9
+ if_name = ['lo'].pack('a16')
10
+ buffer = if_name + 'z' * 24
11
+ # SIOCGIFADDR in /usr/include/bits/ioctls.h
12
+ s.ioctl 0x8915, buffer
13
+ s.close
14
+
15
+ # Interface name should remain unchanged.
16
+ buffer[0, 16].should == if_name
17
+ # lo should have an IPv4 address of 127.0.0.1
18
+ buffer[16, 1].unpack('C').first.should == Socket::AF_INET
19
+ buffer[20, 4].should == "\x7f\0\0\x01"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+ require File.expand_path('../../shared/recv_nonblock', __FILE__)
2
+ require File.expand_path('../../fixtures/classes', __FILE__)
3
+
4
+ describe "Socket::BasicSocket#recv_nonblock" do
5
+ it_behaves_like :socket_recv_nonblock, :recv_nonblock
6
+ end
@@ -0,0 +1,76 @@
1
+ # -*- encoding: US-ASCII -*-
2
+ require File.expand_path('../../fixtures/classes', __FILE__)
3
+
4
+ describe "BasicSocket#recv" do
5
+
6
+ before :each do
7
+ @server = TCPServer.new('127.0.0.1', SocketSpecs.port)
8
+ end
9
+
10
+ after :each do
11
+ @server.closed?.should be_false
12
+ @server.close
13
+ ScratchPad.clear
14
+ end
15
+
16
+ it "receives a specified number of bytes of a message from another socket" do
17
+ t = Thread.new do
18
+ client = @server.accept
19
+ ScratchPad.record client.recv(10)
20
+ client.recv(1) # this recv is important
21
+ client.close
22
+ end
23
+ Thread.pass while t.status and t.status != "sleep"
24
+ t.status.should_not be_nil
25
+
26
+ socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
27
+ socket.send('hello', 0)
28
+ socket.close
29
+
30
+ t.join
31
+ ScratchPad.recorded.should == 'hello'
32
+ end
33
+
34
+ it "accepts flags to specify unusual receiving behaviour" do
35
+ t = Thread.new do
36
+ client = @server.accept
37
+
38
+ # in-band data (TCP), doesn't receive the flag.
39
+ ScratchPad.record client.recv(10)
40
+
41
+ # this recv is important (TODO: explain)
42
+ client.recv(10)
43
+ client.close
44
+ end
45
+ Thread.pass while t.status and t.status != "sleep"
46
+ t.status.should_not be_nil
47
+
48
+ socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
49
+ socket.send('helloU', Socket::MSG_OOB)
50
+ socket.shutdown(1)
51
+ t.join
52
+ socket.close
53
+ ScratchPad.recorded.should == 'hello'
54
+ end
55
+
56
+ it "gets lines delimited with a custom separator" do
57
+ t = Thread.new do
58
+ client = @server.accept
59
+ ScratchPad.record client.gets("\377")
60
+
61
+ # this call is important (TODO: explain)
62
+ client.gets(nil)
63
+ client.close
64
+ end
65
+ Thread.pass while t.status and t.status != "sleep"
66
+ t.status.should_not be_nil
67
+
68
+ socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
69
+ socket.write("firstline\377secondline\377")
70
+ socket.close
71
+
72
+ t.join
73
+ ScratchPad.recorded.should == "firstline\377"
74
+ end
75
+
76
+ end
@@ -0,0 +1,81 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ describe "BasicSocket#send" do
4
+ before :each do
5
+ @server = TCPServer.new('127.0.0.1', SocketSpecs.port)
6
+ @socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
7
+ end
8
+
9
+ after :each do
10
+ @server.closed?.should be_false
11
+ @socket.closed?.should be_false
12
+
13
+ @server.close
14
+ @socket.close
15
+ end
16
+
17
+ it "sends a message to another socket and returns the number of bytes sent" do
18
+ data = ""
19
+ t = Thread.new do
20
+ client = @server.accept
21
+ loop do
22
+ got = client.recv(5)
23
+ break if got.empty?
24
+ data << got
25
+ end
26
+ client.close
27
+ end
28
+ Thread.pass while t.status and t.status != "sleep"
29
+ t.status.should_not be_nil
30
+
31
+ @socket.send('hello', 0).should == 5
32
+ @socket.shutdown(1) # indicate, that we are done sending
33
+ @socket.recv(10)
34
+
35
+ t.join
36
+ data.should == 'hello'
37
+ end
38
+
39
+ it "accepts flags to specify unusual sending behaviour" do
40
+ data = nil
41
+ peek_data = nil
42
+ t = Thread.new do
43
+ client = @server.accept
44
+ peek_data = client.recv(6, Socket::MSG_PEEK)
45
+ data = client.recv(6)
46
+ client.recv(10) # this recv is important
47
+ client.close
48
+ end
49
+ Thread.pass while t.status and t.status != "sleep"
50
+ t.status.should_not be_nil
51
+
52
+ @socket.send('helloU', Socket::MSG_PEEK | Socket::MSG_OOB).should == 6
53
+ @socket.shutdown # indicate, that we are done sending
54
+
55
+ t.join
56
+ peek_data.should == "hello"
57
+ data.should == 'hello'
58
+ end
59
+
60
+ it "accepts a sockaddr as recipient address" do
61
+ data = ""
62
+ t = Thread.new do
63
+ client = @server.accept
64
+ loop do
65
+ got = client.recv(5)
66
+ break if got.empty?
67
+ data << got
68
+ end
69
+ client.close
70
+ end
71
+ Thread.pass while t.status and t.status != "sleep"
72
+ t.status.should_not be_nil
73
+
74
+ sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1")
75
+ @socket.send('hello', 0, sockaddr).should == 5
76
+ @socket.shutdown # indicate, that we are done sending
77
+
78
+ t.join
79
+ data.should == 'hello'
80
+ end
81
+ end
@@ -0,0 +1,333 @@
1
+ require File.expand_path('../../fixtures/classes', __FILE__)
2
+
3
+ describe "BasicSocket#setsockopt" do
4
+
5
+ before(:each) do
6
+ @sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
7
+ end
8
+
9
+ after :each do
10
+ @sock.close unless @sock.closed?
11
+ end
12
+
13
+ describe "using constants" do
14
+ platform_is :windows do
15
+ it "sets the socket linger to 0" do
16
+ linger = pack_int(0, 0)
17
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, linger).should == 0
18
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
19
+
20
+ n.should == pack_int(0)
21
+ end
22
+
23
+ it "sets the socket linger to some positive value" do
24
+ linger = pack_int(64, 64)
25
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, linger).should == 0
26
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
27
+ n.should == pack_int(64)
28
+ end
29
+ end
30
+ platform_is_not :windows do
31
+ it "sets the socket linger to 0" do
32
+ linger = pack_int(0, 0)
33
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, linger).should == 0
34
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
35
+
36
+ n.should == pack_int(0, 0)
37
+ end
38
+
39
+ it "sets the socket linger to some positive value" do
40
+ linger = pack_int(64, 64)
41
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, linger).should == 0
42
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
43
+ a = n.unpack('ii')
44
+ a[0].should_not == 0
45
+ a[1].should == 64
46
+ end
47
+ end
48
+
49
+ it "sets the socket option Socket::SO_OOBINLINE" do
50
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, true).should == 0
51
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
52
+ n.should_not == pack_int(0)
53
+
54
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, false).should == 0
55
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
56
+ n.should == pack_int(0)
57
+
58
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 1).should == 0
59
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
60
+ n.should_not == pack_int(0)
61
+
62
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 0).should == 0
63
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
64
+ n.should == pack_int(0)
65
+
66
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 2).should == 0
67
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
68
+ n.should_not == pack_int(0)
69
+
70
+ platform_is_not :os => :windows do
71
+ lambda {
72
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "")
73
+ }.should raise_error(SystemCallError)
74
+ end
75
+
76
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "blah").should == 0
77
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
78
+ n.should_not == pack_int(0)
79
+
80
+ platform_is_not :os => :windows do
81
+ lambda {
82
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "0")
83
+ }.should raise_error(SystemCallError)
84
+ end
85
+
86
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "\x00\x00\x00\x00").should == 0
87
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
88
+ n.should == pack_int(0)
89
+
90
+ platform_is_not :os => :windows do
91
+ lambda {
92
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "1")
93
+ }.should raise_error(SystemCallError)
94
+ end
95
+
96
+ platform_is_not :os => :windows do
97
+ lambda {
98
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "\x00\x00\x00")
99
+ }.should raise_error(SystemCallError)
100
+ end
101
+
102
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, pack_int(1)).should == 0
103
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
104
+ n.should_not == pack_int(0)
105
+
106
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, pack_int(0)).should == 0
107
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
108
+ n.should == pack_int(0)
109
+
110
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, pack_int(1000)).should == 0
111
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
112
+ n.should_not == pack_int(0)
113
+ end
114
+
115
+ it "sets the socket option Socket::SO_SNDBUF" do
116
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, 4000).should == 0
117
+ sndbuf = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
118
+ # might not always be possible to set to exact size
119
+ sndbuf.unpack('i')[0].should >= 4000
120
+
121
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, true).should == 0
122
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
123
+ n.unpack('i')[0].should >= 1
124
+
125
+ lambda {
126
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, nil).should == 0
127
+ }.should raise_error(TypeError)
128
+
129
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, 1).should == 0
130
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
131
+ n.unpack('i')[0].should >= 1
132
+
133
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, 2).should == 0
134
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
135
+ n.unpack('i')[0].should >= 2
136
+
137
+ lambda {
138
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "")
139
+ }.should raise_error(SystemCallError)
140
+
141
+ lambda {
142
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "bla")
143
+ }.should raise_error(SystemCallError)
144
+
145
+ lambda {
146
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "0")
147
+ }.should raise_error(SystemCallError)
148
+
149
+ lambda {
150
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "1")
151
+ }.should raise_error(SystemCallError)
152
+
153
+ lambda {
154
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "\x00\x00\x00")
155
+ }.should raise_error(SystemCallError)
156
+
157
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "\x00\x00\x01\x00").should == 0
158
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
159
+ n.unpack('i')[0].should >= "\x00\x00\x01\x00".unpack('i')[0]
160
+
161
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, pack_int(4000)).should == 0
162
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
163
+ n.unpack('i')[0].should >= 4000
164
+
165
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, pack_int(1000)).should == 0
166
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
167
+ n.unpack('i')[0].should >= 1000
168
+ end
169
+ end
170
+
171
+ ruby_version_is "1.9" do
172
+ describe "using strings" do
173
+ context "without prefix" do
174
+
175
+ platform_is :windows do
176
+ it "sets the socket linger to 0" do
177
+ linger = pack_int(0, 0)
178
+ @sock.setsockopt("SOCKET", "LINGER", linger).should == 0
179
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
180
+
181
+ n.should == pack_int(0)
182
+ end
183
+
184
+ it "sets the socket linger to some positive value" do
185
+ linger = pack_int(64, 64)
186
+ @sock.setsockopt("SOCKET", "LINGER", linger).should == 0
187
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
188
+ n.should == pack_int(64)
189
+ end
190
+ end
191
+ platform_is_not :windows do
192
+ it "sets the socket linger to 0" do
193
+ linger = pack_int(0, 0)
194
+ @sock.setsockopt("SOCKET", "LINGER", linger).should == 0
195
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
196
+
197
+ n.should == pack_int(0, 0)
198
+ end
199
+
200
+ it "sets the socket linger to some positive value" do
201
+ linger = pack_int(64, 64)
202
+ @sock.setsockopt("SOCKET", "LINGER", linger).should == 0
203
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
204
+ a = n.unpack('ii')
205
+ a[0].should_not == 0
206
+ a[1].should == 64
207
+ end
208
+ end
209
+
210
+ it "sets the socket option Socket::SO_OOBINLINE" do
211
+ @sock.setsockopt("SOCKET", "OOBINLINE", true).should == 0
212
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
213
+ n.should_not == pack_int(0)
214
+
215
+ @sock.setsockopt("SOCKET", "OOBINLINE", false).should == 0
216
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
217
+ n.should == pack_int(0)
218
+
219
+ @sock.setsockopt("SOCKET", "OOBINLINE", 1).should == 0
220
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
221
+ n.should_not == pack_int(0)
222
+
223
+ @sock.setsockopt("SOCKET", "OOBINLINE", 0).should == 0
224
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
225
+ n.should == pack_int(0)
226
+
227
+ @sock.setsockopt("SOCKET", "OOBINLINE", 2).should == 0
228
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
229
+ n.should_not == pack_int(0)
230
+
231
+ platform_is_not :os => :windows do
232
+ lambda {
233
+ @sock.setsockopt("SOCKET", "OOBINLINE", "")
234
+ }.should raise_error(SystemCallError)
235
+ end
236
+
237
+ @sock.setsockopt("SOCKET", "OOBINLINE", "blah").should == 0
238
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
239
+ n.should_not == pack_int(0)
240
+
241
+ platform_is_not :os => :windows do
242
+ lambda {
243
+ @sock.setsockopt("SOCKET", "OOBINLINE", "0")
244
+ }.should raise_error(SystemCallError)
245
+ end
246
+
247
+ @sock.setsockopt("SOCKET", "OOBINLINE", "\x00\x00\x00\x00").should == 0
248
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
249
+ n.should == pack_int(0)
250
+
251
+ platform_is_not :os => :windows do
252
+ lambda {
253
+ @sock.setsockopt("SOCKET", "OOBINLINE", "1")
254
+ }.should raise_error(SystemCallError)
255
+ end
256
+
257
+ platform_is_not :os => :windows do
258
+ lambda {
259
+ @sock.setsockopt("SOCKET", "OOBINLINE", "\x00\x00\x00")
260
+ }.should raise_error(SystemCallError)
261
+ end
262
+
263
+ @sock.setsockopt("SOCKET", "OOBINLINE", pack_int(1)).should == 0
264
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
265
+ n.should_not == pack_int(0)
266
+
267
+ @sock.setsockopt("SOCKET", "OOBINLINE", pack_int(0)).should == 0
268
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
269
+ n.should == pack_int(0)
270
+
271
+ @sock.setsockopt("SOCKET", "OOBINLINE", pack_int(1000)).should == 0
272
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
273
+ n.should_not == pack_int(0)
274
+ end
275
+
276
+ it "sets the socket option Socket::SO_SNDBUF" do
277
+ @sock.setsockopt("SOCKET", "SNDBUF", 4000).should == 0
278
+ sndbuf = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
279
+ # might not always be possible to set to exact size
280
+ sndbuf.unpack('i')[0].should >= 4000
281
+
282
+ @sock.setsockopt("SOCKET", "SNDBUF", true).should == 0
283
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
284
+ n.unpack('i')[0].should >= 1
285
+
286
+ lambda {
287
+ @sock.setsockopt("SOCKET", "SNDBUF", nil).should == 0
288
+ }.should raise_error(TypeError)
289
+
290
+ @sock.setsockopt("SOCKET", "SNDBUF", 1).should == 0
291
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
292
+ n.unpack('i')[0].should >= 1
293
+
294
+ @sock.setsockopt("SOCKET", "SNDBUF", 2).should == 0
295
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
296
+ n.unpack('i')[0].should >= 2
297
+
298
+ lambda {
299
+ @sock.setsockopt("SOCKET", "SNDBUF", "")
300
+ }.should raise_error(SystemCallError)
301
+
302
+ lambda {
303
+ @sock.setsockopt("SOCKET", "SNDBUF", "bla")
304
+ }.should raise_error(SystemCallError)
305
+
306
+ lambda {
307
+ @sock.setsockopt("SOCKET", "SNDBUF", "0")
308
+ }.should raise_error(SystemCallError)
309
+
310
+ lambda {
311
+ @sock.setsockopt("SOCKET", "SNDBUF", "1")
312
+ }.should raise_error(SystemCallError)
313
+
314
+ lambda {
315
+ @sock.setsockopt("SOCKET", "SNDBUF", "\x00\x00\x00")
316
+ }.should raise_error(SystemCallError)
317
+
318
+ @sock.setsockopt("SOCKET", "SNDBUF", "\x00\x00\x01\x00").should == 0
319
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
320
+ n.unpack('i')[0].should >= "\x00\x00\x01\x00".unpack('i')[0]
321
+
322
+ @sock.setsockopt("SOCKET", "SNDBUF", pack_int(4000)).should == 0
323
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
324
+ n.unpack('i')[0].should >= 4000
325
+
326
+ @sock.setsockopt("SOCKET", "SNDBUF", pack_int(1000)).should == 0
327
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
328
+ n.unpack('i')[0].should >= 1000
329
+ end
330
+ end
331
+ end
332
+ end
333
+ end