uringmachine 0.4 → 0.5.1

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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -1
  3. data/CHANGELOG.md +16 -0
  4. data/README.md +44 -1
  5. data/TODO.md +12 -3
  6. data/examples/bm_snooze.rb +89 -0
  7. data/examples/bm_sqlite.rb +89 -0
  8. data/examples/bm_write.rb +56 -0
  9. data/examples/dns_client.rb +12 -0
  10. data/examples/http_server.rb +42 -43
  11. data/examples/pg.rb +85 -0
  12. data/examples/server_client.rb +64 -0
  13. data/examples/snooze.rb +44 -0
  14. data/examples/stream.rb +85 -0
  15. data/examples/write_dev_null.rb +16 -0
  16. data/ext/um/extconf.rb +81 -14
  17. data/ext/um/um.c +468 -414
  18. data/ext/um/um.h +149 -40
  19. data/ext/um/um_async_op.c +40 -0
  20. data/ext/um/um_async_op_class.c +136 -0
  21. data/ext/um/um_buffer.c +49 -0
  22. data/ext/um/um_class.c +176 -44
  23. data/ext/um/um_const.c +174 -9
  24. data/ext/um/um_ext.c +8 -0
  25. data/ext/um/um_mutex_class.c +47 -0
  26. data/ext/um/um_op.c +89 -111
  27. data/ext/um/um_queue_class.c +58 -0
  28. data/ext/um/um_ssl.c +850 -0
  29. data/ext/um/um_ssl.h +22 -0
  30. data/ext/um/um_ssl_class.c +138 -0
  31. data/ext/um/um_sync.c +273 -0
  32. data/ext/um/um_utils.c +1 -1
  33. data/lib/uringmachine/dns_resolver.rb +84 -0
  34. data/lib/uringmachine/ssl/context_builder.rb +96 -0
  35. data/lib/uringmachine/ssl.rb +394 -0
  36. data/lib/uringmachine/version.rb +1 -1
  37. data/lib/uringmachine.rb +27 -3
  38. data/supressions/ruby.supp +71 -0
  39. data/test/helper.rb +6 -0
  40. data/test/test_async_op.rb +119 -0
  41. data/test/test_ssl.rb +155 -0
  42. data/test/test_um.rb +464 -47
  43. data/uringmachine.gemspec +3 -2
  44. data/vendor/liburing/.gitignore +5 -0
  45. data/vendor/liburing/CHANGELOG +1 -0
  46. data/vendor/liburing/configure +32 -0
  47. data/vendor/liburing/examples/Makefile +1 -0
  48. data/vendor/liburing/examples/reg-wait.c +159 -0
  49. data/vendor/liburing/liburing.spec +1 -1
  50. data/vendor/liburing/src/include/liburing/io_uring.h +48 -2
  51. data/vendor/liburing/src/include/liburing.h +28 -2
  52. data/vendor/liburing/src/int_flags.h +10 -3
  53. data/vendor/liburing/src/liburing-ffi.map +13 -2
  54. data/vendor/liburing/src/liburing.map +9 -0
  55. data/vendor/liburing/src/queue.c +25 -16
  56. data/vendor/liburing/src/register.c +73 -4
  57. data/vendor/liburing/src/setup.c +46 -18
  58. data/vendor/liburing/src/setup.h +6 -0
  59. data/vendor/liburing/test/Makefile +7 -0
  60. data/vendor/liburing/test/cmd-discard.c +427 -0
  61. data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
  62. data/vendor/liburing/test/file-exit-unreg.c +48 -0
  63. data/vendor/liburing/test/io_uring_passthrough.c +2 -0
  64. data/vendor/liburing/test/io_uring_register.c +13 -2
  65. data/vendor/liburing/test/napi-test.c +1 -1
  66. data/vendor/liburing/test/no-mmap-inval.c +1 -1
  67. data/vendor/liburing/test/read-mshot-empty.c +2 -0
  68. data/vendor/liburing/test/read-mshot-stdin.c +121 -0
  69. data/vendor/liburing/test/read-mshot.c +6 -0
  70. data/vendor/liburing/test/recvsend_bundle.c +2 -2
  71. data/vendor/liburing/test/reg-fd-only.c +1 -1
  72. data/vendor/liburing/test/reg-wait.c +251 -0
  73. data/vendor/liburing/test/regbuf-clone.c +458 -0
  74. data/vendor/liburing/test/resize-rings.c +643 -0
  75. data/vendor/liburing/test/rsrc_tags.c +1 -1
  76. data/vendor/liburing/test/sqpoll-sleep.c +39 -8
  77. data/vendor/liburing/test/sqwait.c +136 -0
  78. data/vendor/liburing/test/sync-cancel.c +8 -1
  79. data/vendor/liburing/test/timeout.c +13 -8
  80. metadata +52 -8
  81. data/examples/http_server_multishot.rb +0 -57
  82. data/examples/http_server_simpler.rb +0 -34
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/uringmachine'
4
+
5
+ @machine = UM.new
6
+
7
+ class UM::Stream
8
+ def initialize(machine, fd)
9
+ @machine, @fd, @bgid = machine, fd
10
+ @buffer = +''
11
+ @ofs_head = 0
12
+ @ofs_tail = 0
13
+ end
14
+
15
+ def feed
16
+ if (@ofs_head == @ofs_tail) && (@ofs_head >= 4096)
17
+ @buffer = +''
18
+ @ofs_head = @ofs_tail = 0
19
+ end
20
+ ret = @machine.read(@fd, @buffer, 65536, @ofs_tail)
21
+ if ret == 0
22
+ @eof = true
23
+ return false
24
+ end
25
+
26
+ @ofs_tail += ret
27
+ true
28
+ end
29
+
30
+ def read(len)
31
+ if @ofs_head + len > @ofs_tail
32
+ feed
33
+ end
34
+
35
+ str = @buffer[@ofs_head, len]
36
+ @ofs_head += str.bytesize
37
+ str
38
+ end
39
+
40
+ def gets(sep = $/, _limit = nil, _chomp: nil)
41
+ if sep.is_a?(Integer)
42
+ sep = $/
43
+ _limit = sep
44
+ end
45
+ sep_size = sep.bytesize
46
+
47
+ while true
48
+ idx = @buffer.index(sep, @ofs_head)
49
+ if idx
50
+ str = @buffer[@ofs_head, idx + sep_size]
51
+ @ofs_head += str.bytesize
52
+ return str
53
+ end
54
+
55
+ return nil if !feed
56
+ end
57
+ end
58
+ end
59
+
60
+ $machine = UringMachine.new
61
+
62
+ server_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
63
+ $machine.setsockopt(server_fd, UM::SOL_SOCKET, UM::SO_REUSEADDR, true)
64
+ $machine.bind(server_fd, '127.0.0.1', 1234)
65
+ $machine.listen(server_fd, UM::SOMAXCONN)
66
+ puts 'Listening on port 1234'
67
+
68
+ def handle_connection(fd)
69
+ stream = UM::Stream.new($machine, fd)
70
+
71
+ while (l = stream.gets)
72
+ $machine.write(fd, "You said: #{l}")
73
+ end
74
+ rescue Exception => e
75
+ puts "Got error #{e.inspect}, closing connection"
76
+ $machine.close(fd) rescue nil
77
+ end
78
+
79
+ main = Fiber.current
80
+ trap('SIGINT') { $machine.spin { $machine.schedule(main, SystemExit.new) } }
81
+
82
+ $machine.accept_each(server_fd) do |fd|
83
+ puts "Connection accepted fd #{fd}"
84
+ $machine.spin(fd) { handle_connection(_1) }
85
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/uringmachine'
4
+
5
+ ITERATIONS = 1000
6
+ DEV_NULL = File.open('/dev/null', 'w')
7
+ FD = DEV_NULL.fileno
8
+ BUF = ('*' * 8192).freeze
9
+
10
+ $machine = UringMachine.new
11
+
12
+ def run_um_write
13
+ $machine.write(FD, BUF)
14
+ end
15
+
16
+ 1000.times { run_um_write }
data/ext/um/extconf.rb CHANGED
@@ -6,10 +6,66 @@ require 'rbconfig'
6
6
 
7
7
  dir_config 'um_ext'
8
8
 
9
+ def config_ssl
10
+ # don't use pkg_config('openssl') if '--with-openssl-dir' is used
11
+ has_openssl_dir = dir_config('openssl').any? ||
12
+ RbConfig::CONFIG['configure_args']&.include?('openssl')
13
+
14
+ found_pkg_config = !has_openssl_dir && pkg_config('openssl')
15
+
16
+ found_ssl = if !$mingw && found_pkg_config
17
+ puts '──── Using OpenSSL pkgconfig (openssl.pc) ────'
18
+ true
19
+ elsif have_library('libcrypto', 'BIO_read') && have_library('libssl', 'SSL_CTX_new')
20
+ true
21
+ elsif %w'crypto libeay32'.find {|crypto| have_library(crypto, 'BIO_read')} &&
22
+ %w'ssl ssleay32'.find {|ssl| have_library(ssl, 'SSL_CTX_new')}
23
+ true
24
+ else
25
+ puts '** Puma will be compiled without SSL support'
26
+ false
27
+ end
28
+
29
+ if found_ssl
30
+ have_header "openssl/bio.h"
31
+
32
+ ssl_h = "openssl/ssl.h".freeze
33
+
34
+ puts "\n──── Below are yes for 1.0.2 & later ────"
35
+ have_func "DTLS_method" , ssl_h
36
+ have_func "SSL_CTX_set_session_cache_mode(NULL, 0)", ssl_h
37
+
38
+ puts "\n──── Below are yes for 1.1.0 & later ────"
39
+ have_func "TLS_server_method" , ssl_h
40
+ have_func "SSL_CTX_set_min_proto_version(NULL, 0)" , ssl_h
41
+
42
+ puts "\n──── Below is yes for 1.1.0 and later, but isn't documented until 3.0.0 ────"
43
+ # https://github.com/openssl/openssl/blob/OpenSSL_1_1_0/include/openssl/ssl.h#L1159
44
+ have_func "SSL_CTX_set_dh_auto(NULL, 0)" , ssl_h
45
+
46
+ puts "\n──── Below is yes for 1.1.1 & later ────"
47
+ have_func "SSL_CTX_set_ciphersuites(NULL, \"\")" , ssl_h
48
+
49
+ puts "\n──── Below is yes for 3.0.0 & later ────"
50
+ have_func "SSL_get1_peer_certificate" , ssl_h
51
+
52
+ puts ''
53
+
54
+ # Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
55
+ if Random.respond_to?(:bytes)
56
+ $defs.push "-DHAVE_RANDOM_BYTES"
57
+ puts "checking for Random.bytes... yes"
58
+ else
59
+ puts "checking for Random.bytes... no"
60
+ end
61
+ end
62
+ end
63
+
9
64
  KERNEL_INFO_RE = /Linux (\d)\.(\d+)(?:\.)?((?:\d+\.?)*)(?:\-)?([\w\-]+)?/
10
65
  def get_config
11
- config = { linux: !!(RUBY_PLATFORM =~ /linux/) }
12
- raise "UringMachine only works on Linux!" if !config[:linux]
66
+ if RUBY_PLATFORM !~ /linux/
67
+ raise "UringMachine only works on Linux!"
68
+ end
13
69
 
14
70
  kernel_info = `uname -sr`
15
71
  m = kernel_info.match(KERNEL_INFO_RE)
@@ -20,16 +76,22 @@ def get_config
20
76
  combined_version = version.to_i * 100 + major_revision.to_i
21
77
  raise "UringMachine requires kernel version 6.4 or newer!" if combined_version < 604
22
78
 
23
- config[:kernel_version] = combined_version
24
- config[:submit_all_flag] = combined_version >= 518
25
- config[:coop_taskrun_flag] = combined_version >= 519
26
- config[:single_issuer_flag] = combined_version >= 600
27
- config[:prep_bind] = combined_version >= 611
28
- config[:prep_listen] = combined_version >= 611
29
-
30
- config
79
+ {
80
+ kernel_version: combined_version,
81
+ submit_all_flag: combined_version >= 518,
82
+ coop_taskrun_flag: combined_version >= 519,
83
+ single_issuer_flag: combined_version >= 600,
84
+ prep_bind: combined_version >= 611,
85
+ prep_listen: combined_version >= 611,
86
+ prep_cmd_sock: combined_version >= 607,
87
+ prep_futex: combined_version >= 607,
88
+ prep_waitid: combined_version >= 607,
89
+ prep_read_multishot: combined_version >= 607
90
+ }
31
91
  end
32
92
 
93
+ config_ssl
94
+
33
95
  config = get_config
34
96
  puts "Building UringMachine (\n#{config.map { |(k, v)| " #{k}: #{v}\n"}.join})"
35
97
 
@@ -51,10 +113,15 @@ if !find_library('uring', nil, File.join(liburing_path, 'src'))
51
113
  raise "Couldn't find liburing.a"
52
114
  end
53
115
 
54
- $defs << '-DHAVE_IORING_SETUP_SUBMIT_ALL' if config[:submit_all_flag]
55
- $defs << '-DHAVE_IORING_SETUP_COOP_TASKRUN' if config[:coop_taskrun_flag]
56
- $defs << '-DHAVE_IO_URING_PREP_BIND' if config[:prep_bind]
57
- $defs << '-DHAVE_IO_URING_PREP_LISTEN' if config[:prep_listen]
116
+ $defs << "-DUM_KERNEL_VERSION=#{config[:kernel_version]}"
117
+ $defs << '-DHAVE_IORING_SETUP_SUBMIT_ALL' if config[:submit_all_flag]
118
+ $defs << '-DHAVE_IORING_SETUP_COOP_TASKRUN' if config[:coop_taskrun_flag]
119
+ $defs << '-DHAVE_IO_URING_PREP_BIND' if config[:prep_bind]
120
+ $defs << '-DHAVE_IO_URING_PREP_LISTEN' if config[:prep_listen]
121
+ $defs << '-DHAVE_IO_URING_PREP_CMD_SOCK' if config[:prep_cmd_sock]
122
+ $defs << '-DHAVE_IO_URING_PREP_FUTEX' if config[:prep_futex]
123
+ $defs << '-DHAVE_IO_URING_PREP_WAITID' if config[:prep_waitid]
124
+ $defs << '-DHAVE_IO_URING_PREP_READ_MULTISHOT' if config[:prep_read_multishot]
58
125
  $CFLAGS << ' -Wno-pointer-arith'
59
126
 
60
127
  CONFIG['optflags'] << ' -fno-strict-aliasing'