polyphony 0.97 → 0.99

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 (194) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/examples/io/https_server_sni_2.rb +14 -8
  4. data/examples/io/irb.rb +1 -1
  5. data/ext/polyphony/backend_common.c +30 -0
  6. data/ext/polyphony/backend_common.h +1 -0
  7. data/ext/polyphony/backend_io_uring.c +125 -0
  8. data/ext/polyphony/backend_libev.c +135 -0
  9. data/ext/polyphony/extconf.rb +6 -5
  10. data/ext/polyphony/io_extensions.c +2 -0
  11. data/ext/polyphony/libev.h +0 -2
  12. data/ext/polyphony/polyphony.c +10 -0
  13. data/ext/polyphony/polyphony.h +2 -0
  14. data/lib/polyphony/adapters/irb.rb +0 -2
  15. data/lib/polyphony/core/sync.rb +53 -0
  16. data/lib/polyphony/extensions/io.rb +39 -14
  17. data/lib/polyphony/extensions/openssl.rb +1 -1
  18. data/lib/polyphony/extensions/socket.rb +30 -1
  19. data/lib/polyphony/version.rb +1 -1
  20. data/lib/polyphony.rb +4 -0
  21. data/test/test_io.rb +14 -7
  22. data/test/test_socket.rb +131 -10
  23. data/test/test_sync.rb +42 -1
  24. data/test/test_thread.rb +2 -1
  25. data/vendor/liburing/.github/workflows/build.yml +7 -16
  26. data/vendor/liburing/.gitignore +5 -0
  27. data/vendor/liburing/CHANGELOG +23 -1
  28. data/vendor/liburing/Makefile +4 -3
  29. data/vendor/liburing/Makefile.common +1 -0
  30. data/vendor/liburing/README +48 -0
  31. data/vendor/liburing/configure +76 -6
  32. data/vendor/liburing/debian/changelog +11 -0
  33. data/vendor/liburing/debian/control +7 -16
  34. data/vendor/liburing/debian/liburing-dev.manpages +3 -6
  35. data/vendor/liburing/debian/liburing2.install +1 -0
  36. data/vendor/liburing/debian/liburing2.symbols +56 -0
  37. data/vendor/liburing/debian/rules +15 -68
  38. data/vendor/liburing/examples/Makefile +4 -0
  39. data/vendor/liburing/examples/io_uring-close-test.c +123 -0
  40. data/vendor/liburing/examples/io_uring-udp.c +1 -1
  41. data/vendor/liburing/examples/send-zerocopy.c +315 -56
  42. data/vendor/liburing/examples/ucontext-cp.c +2 -17
  43. data/vendor/liburing/liburing-ffi.pc.in +12 -0
  44. data/vendor/liburing/liburing.pc.in +1 -1
  45. data/vendor/liburing/liburing.spec +1 -1
  46. data/vendor/liburing/make-debs.sh +3 -3
  47. data/vendor/liburing/man/IO_URING_CHECK_VERSION.3 +1 -0
  48. data/vendor/liburing/man/IO_URING_VERSION_MAJOR.3 +1 -0
  49. data/vendor/liburing/man/IO_URING_VERSION_MINOR.3 +1 -0
  50. data/vendor/liburing/man/io_uring_buf_ring_add.3 +6 -6
  51. data/vendor/liburing/man/io_uring_check_version.3 +72 -0
  52. data/vendor/liburing/man/io_uring_close_ring_fd.3 +43 -0
  53. data/vendor/liburing/man/io_uring_major_version.3 +1 -0
  54. data/vendor/liburing/man/io_uring_minor_version.3 +1 -0
  55. data/vendor/liburing/man/io_uring_prep_accept.3 +1 -1
  56. data/vendor/liburing/man/io_uring_prep_fgetxattr.3 +1 -0
  57. data/vendor/liburing/man/io_uring_prep_fsetxattr.3 +1 -0
  58. data/vendor/liburing/man/io_uring_prep_getxattr.3 +61 -0
  59. data/vendor/liburing/man/io_uring_prep_link_timeout.3 +94 -0
  60. data/vendor/liburing/man/io_uring_prep_msg_ring.3 +22 -2
  61. data/vendor/liburing/man/io_uring_prep_msg_ring_cqe_flags.3 +1 -0
  62. data/vendor/liburing/man/io_uring_prep_poll_add.3 +1 -1
  63. data/vendor/liburing/man/io_uring_prep_provide_buffers.3 +18 -9
  64. data/vendor/liburing/man/io_uring_prep_readv.3 +3 -3
  65. data/vendor/liburing/man/io_uring_prep_readv2.3 +3 -3
  66. data/vendor/liburing/man/io_uring_prep_recv.3 +5 -5
  67. data/vendor/liburing/man/io_uring_prep_recvmsg.3 +4 -4
  68. data/vendor/liburing/man/io_uring_prep_send.3 +9 -0
  69. data/vendor/liburing/man/io_uring_prep_send_set_addr.3 +38 -0
  70. data/vendor/liburing/man/io_uring_prep_send_zc.3 +39 -7
  71. data/vendor/liburing/man/io_uring_prep_send_zc_fixed.3 +1 -0
  72. data/vendor/liburing/man/io_uring_prep_sendmsg.3 +20 -0
  73. data/vendor/liburing/man/io_uring_prep_sendmsg_zc.3 +1 -0
  74. data/vendor/liburing/man/io_uring_prep_setxattr.3 +64 -0
  75. data/vendor/liburing/man/io_uring_prep_splice.3 +40 -0
  76. data/vendor/liburing/man/io_uring_prep_writev.3 +2 -2
  77. data/vendor/liburing/man/io_uring_prep_writev2.3 +2 -2
  78. data/vendor/liburing/man/io_uring_recvmsg_out.3 +13 -9
  79. data/vendor/liburing/man/io_uring_register.2 +15 -9
  80. data/vendor/liburing/man/io_uring_register_buf_ring.3 +4 -4
  81. data/vendor/liburing/man/io_uring_register_buffers.3 +49 -6
  82. data/vendor/liburing/man/io_uring_register_buffers_sparse.3 +1 -0
  83. data/vendor/liburing/man/io_uring_register_buffers_tags.3 +1 -0
  84. data/vendor/liburing/man/io_uring_register_buffers_update_tag.3 +1 -0
  85. data/vendor/liburing/man/io_uring_register_files.3 +60 -5
  86. data/vendor/liburing/man/io_uring_register_files_tags.3 +1 -0
  87. data/vendor/liburing/man/io_uring_register_files_update.3 +1 -0
  88. data/vendor/liburing/man/io_uring_register_files_update_tag.3 +1 -0
  89. data/vendor/liburing/man/io_uring_setup.2 +31 -2
  90. data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +1 -1
  91. data/vendor/liburing/src/Makefile +25 -3
  92. data/vendor/liburing/src/ffi.c +15 -0
  93. data/vendor/liburing/src/include/liburing/io_uring.h +30 -7
  94. data/vendor/liburing/src/include/liburing.h +190 -148
  95. data/vendor/liburing/src/int_flags.h +1 -0
  96. data/vendor/liburing/src/lib.h +5 -16
  97. data/vendor/liburing/src/liburing-ffi.map +172 -0
  98. data/vendor/liburing/src/liburing.map +11 -0
  99. data/vendor/liburing/src/nolibc.c +9 -2
  100. data/vendor/liburing/src/queue.c +2 -2
  101. data/vendor/liburing/src/register.c +66 -96
  102. data/vendor/liburing/src/setup.c +5 -4
  103. data/vendor/liburing/src/version.c +21 -0
  104. data/vendor/liburing/test/232c93d07b74.c +3 -3
  105. data/vendor/liburing/test/35fa71a030ca.c +3 -3
  106. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  107. data/vendor/liburing/test/917257daa0fe.c +1 -1
  108. data/vendor/liburing/test/Makefile +27 -7
  109. data/vendor/liburing/test/a0908ae19763.c +2 -2
  110. data/vendor/liburing/test/a4c0b3decb33.c +2 -2
  111. data/vendor/liburing/test/accept-link.c +4 -4
  112. data/vendor/liburing/test/accept-reuse.c +5 -7
  113. data/vendor/liburing/test/accept.c +34 -31
  114. data/vendor/liburing/test/b19062a56726.c +1 -1
  115. data/vendor/liburing/test/buf-ring.c +58 -4
  116. data/vendor/liburing/test/ce593a6c480a.c +2 -2
  117. data/vendor/liburing/test/close-opath.c +2 -1
  118. data/vendor/liburing/test/connect.c +8 -0
  119. data/vendor/liburing/test/cq-overflow.c +14 -8
  120. data/vendor/liburing/test/d4ae271dfaae.c +1 -1
  121. data/vendor/liburing/test/defer-taskrun.c +64 -9
  122. data/vendor/liburing/test/defer.c +1 -1
  123. data/vendor/liburing/test/double-poll-crash.c +3 -3
  124. data/vendor/liburing/test/eeed8b54e0df.c +8 -3
  125. data/vendor/liburing/test/eploop.c +74 -0
  126. data/vendor/liburing/test/eventfd-ring.c +1 -1
  127. data/vendor/liburing/test/eventfd.c +1 -1
  128. data/vendor/liburing/test/evloop.c +73 -0
  129. data/vendor/liburing/test/exit-no-cleanup.c +1 -1
  130. data/vendor/liburing/test/fadvise.c +1 -1
  131. data/vendor/liburing/test/fc2a85cb02ef.c +3 -3
  132. data/vendor/liburing/test/fd-pass.c +35 -16
  133. data/vendor/liburing/test/file-register.c +61 -0
  134. data/vendor/liburing/test/file-verify.c +2 -2
  135. data/vendor/liburing/test/files-exit-hang-timeout.c +2 -2
  136. data/vendor/liburing/test/fixed-link.c +1 -1
  137. data/vendor/liburing/test/fsnotify.c +118 -0
  138. data/vendor/liburing/test/hardlink.c +1 -1
  139. data/vendor/liburing/test/helpers.c +54 -2
  140. data/vendor/liburing/test/helpers.h +4 -0
  141. data/vendor/liburing/test/io-cancel.c +3 -1
  142. data/vendor/liburing/test/io_uring_passthrough.c +39 -8
  143. data/vendor/liburing/test/io_uring_setup.c +3 -80
  144. data/vendor/liburing/test/iopoll-overflow.c +118 -0
  145. data/vendor/liburing/test/iopoll.c +90 -4
  146. data/vendor/liburing/test/lfs-openat-write.c +7 -9
  147. data/vendor/liburing/test/lfs-openat.c +6 -8
  148. data/vendor/liburing/test/link_drain.c +31 -5
  149. data/vendor/liburing/test/madvise.c +1 -1
  150. data/vendor/liburing/test/msg-ring-flags.c +192 -0
  151. data/vendor/liburing/test/msg-ring-overflow.c +159 -0
  152. data/vendor/liburing/test/msg-ring.c +173 -13
  153. data/vendor/liburing/test/multicqes_drain.c +22 -19
  154. data/vendor/liburing/test/nvme.h +4 -3
  155. data/vendor/liburing/test/pipe-bug.c +95 -0
  156. data/vendor/liburing/test/poll-link.c +3 -3
  157. data/vendor/liburing/test/poll-many.c +41 -19
  158. data/vendor/liburing/test/poll-mshot-overflow.c +105 -2
  159. data/vendor/liburing/test/poll-race-mshot.c +292 -0
  160. data/vendor/liburing/test/poll-race.c +105 -0
  161. data/vendor/liburing/test/poll.c +244 -26
  162. data/vendor/liburing/test/pollfree.c +5 -5
  163. data/vendor/liburing/test/read-before-exit.c +20 -3
  164. data/vendor/liburing/test/read-write.c +2 -0
  165. data/vendor/liburing/test/recv-multishot.c +96 -3
  166. data/vendor/liburing/test/reg-reg-ring.c +90 -0
  167. data/vendor/liburing/test/rename.c +1 -1
  168. data/vendor/liburing/test/ring-leak.c +0 -1
  169. data/vendor/liburing/test/ring-leak2.c +1 -1
  170. data/vendor/liburing/test/ringbuf-read.c +10 -6
  171. data/vendor/liburing/test/send-zerocopy.c +273 -103
  172. data/vendor/liburing/test/send_recv.c +7 -4
  173. data/vendor/liburing/test/sendmsg_fs_cve.c +2 -2
  174. data/vendor/liburing/test/single-issuer.c +7 -9
  175. data/vendor/liburing/test/skip-cqe.c +3 -4
  176. data/vendor/liburing/test/socket.c +0 -1
  177. data/vendor/liburing/test/sq-poll-dup.c +10 -3
  178. data/vendor/liburing/test/sq-poll-kthread.c +1 -1
  179. data/vendor/liburing/test/sq-poll-share.c +3 -2
  180. data/vendor/liburing/test/sqpoll-cancel-hang.c +17 -6
  181. data/vendor/liburing/test/sqpoll-disable-exit.c +4 -4
  182. data/vendor/liburing/test/symlink.c +2 -1
  183. data/vendor/liburing/test/test.h +2 -1
  184. data/vendor/liburing/test/timeout-new.c +11 -7
  185. data/vendor/liburing/test/timeout.c +1 -2
  186. data/vendor/liburing/test/unlink.c +1 -1
  187. data/vendor/liburing/test/version.c +25 -0
  188. data/vendor/liburing/test/wakeup-hang.c +1 -1
  189. data/vendor/liburing/test/xattr.c +8 -4
  190. metadata +42 -6
  191. data/vendor/liburing/debian/compat +0 -1
  192. data/vendor/liburing/debian/liburing1-udeb.install +0 -1
  193. data/vendor/liburing/debian/liburing1.install +0 -1
  194. data/vendor/liburing/debian/liburing1.symbols +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a8218fc4160e0772ee3aada1f72ea9d063724ccf9b0aee7dfa6e9e4d69ebfe4
4
- data.tar.gz: 74aae84e991cd4330ad282553061b29e71a6434ce2dafc9985c62feb3a966a68
3
+ metadata.gz: 4696bb7b13f68b379c29d5c38257e57c13aefd299f88727107e2f0f0a3c7d360
4
+ data.tar.gz: 94a3eeb8575d0d5fe6f143ab41351024b50c4c4cf919edec6c8155d9ead2831e
5
5
  SHA512:
6
- metadata.gz: 772d0be4ef2f723fa27cc5ecb8ef9e9b5d012c501a364ab23dce7d145fc6d156d5e219e52e871a2aadb41a397c5fb044c8aaee9b42906f4894ff3447af0e93ba
7
- data.tar.gz: b74d6958ea8a77ffee45aed8184091b5ef54cb4fcaca9798351533b13d2f2202f28ab95f56a26e09692bf40f00e723d2df9c99007dbe10631d1c69c523fb3a58
6
+ metadata.gz: 9e1798e18b0e7a35104009d6f480191f5ed5efd7dee69189d443cb57ab8ca2f8fd75105234cd60f52ecea2348a8c3d85f152aa869374ea8dfbab8895a2015b04
7
+ data.tar.gz: 835b2be245f60b04d5b750bcce6e679b11c671e31c3d0269aeafaa961c52c501193f67cf00f4f7cc5570cab499105d025863189767db8ae79f961a62d903b173
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## 0.99 2023-03-09
2
+
3
+ - Add missing Mutex API methods (#76)
4
+ - Fix `IO.foreach` and `IO#each_line` (#74)
5
+ - Fix `SSLServer#accept_loop` (#59)
6
+ - Update liburing
7
+
8
+ ## 0.98 2023-03-08
9
+
10
+ - Add basic support for UDP sockets
11
+ - Fix `IO#read` to return empty string when reading length zero
12
+ - Fix hang on `require 'polyphony'` in irb session
13
+
1
14
  ## 0.97 2023-02-28
2
15
 
3
16
  - Fix working with IRB (#5)
@@ -27,15 +27,21 @@ server = Polyphony::Net.tcp_listen('localhost', 1234, opts)
27
27
 
28
28
  puts 'Serving HTTPS on port 1234'
29
29
 
30
- # server.accept_loop do |socket|
31
- server.accept_loop do |socket|
32
- # while (socket = (server.accept)
33
- spin do
34
- while (data = socket.gets("\n", 8192))
35
- if data.chomp.empty?
36
- socket << "HTTP/1.1 200 OK\nConnection: close\nContent-Length: 4\n\nfoo\n"
37
- break
30
+ begin
31
+ server.accept_loop(false) do |socket|
32
+ spin do
33
+ while (data = socket.gets("\n", 8192))
34
+ if data.chomp.empty?
35
+ socket << "HTTP/1.1 200 OK\nConnection: close\nContent-Length: 4\n\nfoo\n"
36
+ break
37
+ end
38
38
  end
39
+ rescue OpenSSL::SSL::SSLError
40
+ # ignore
39
41
  end
40
42
  end
43
+ rescue => e
44
+ puts '*' * 40
45
+ p e
46
+ puts e.backtrace.join("\n")
41
47
  end
data/examples/io/irb.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'bundler/setup'
4
4
  require 'irb'
5
- require 'polyphony/adapters/irb'
5
+ require 'polyphony'
6
6
 
7
7
  $counter = 0
8
8
  timer = spin do
@@ -501,6 +501,36 @@ int backend_getaddrinfo(VALUE host, VALUE port, struct sockaddr **ai_addr) {
501
501
  return addrinfo_result->ai_addrlen;
502
502
  }
503
503
 
504
+ inline VALUE name_to_addrinfo(void *name, socklen_t len) {
505
+ switch(((struct sockaddr *)name)->sa_family) {
506
+ case AF_INET:
507
+ {
508
+ struct sockaddr_in *info = name;
509
+ char buf[INET_ADDRSTRLEN];
510
+
511
+ VALUE port = INT2NUM(ntohs(info->sin_port));
512
+ if (!inet_ntop(AF_INET, &info->sin_addr, buf, sizeof(buf)))
513
+ rb_raise(rb_eRuntimeError, "Failed to get AF_INET addr");
514
+ VALUE addr = rb_str_new_cstr(buf);
515
+ return rb_ary_new_from_args(4, rb_str_new_literal("AF_INET"), port, addr, addr);
516
+ RB_GC_GUARD(addr);
517
+ }
518
+ case AF_INET6:
519
+ {
520
+ struct sockaddr_in6 *info = name;
521
+ char buf[INET6_ADDRSTRLEN];
522
+
523
+ VALUE port = INT2NUM(ntohs(info->sin6_port));
524
+ if (!inet_ntop(AF_INET6, &info->sin6_addr, buf, sizeof(buf)))
525
+ rb_raise(rb_eRuntimeError, "Failed to get AF_INET addr");
526
+ VALUE addr = rb_str_new_cstr(buf);
527
+ return rb_ary_new_from_args(4, rb_str_new_literal("AF_INET6"), port, addr, addr);
528
+ RB_GC_GUARD(addr);
529
+ }
530
+ }
531
+ return Qnil;
532
+ }
533
+
504
534
  inline struct backend_buffer_spec backend_get_buffer_spec(VALUE in, int rw) {
505
535
  if (FIXNUM_P(in)) {
506
536
  struct buffer_spec *spec = FIX2PTR(in);
@@ -148,5 +148,6 @@ void set_fd_blocking_mode(int fd, int blocking);
148
148
  void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking);
149
149
  void backend_setup_stats_symbols();
150
150
  int backend_getaddrinfo(VALUE host, VALUE port, struct sockaddr **ai_addr);
151
+ VALUE name_to_addrinfo(void *name, socklen_t len);
151
152
 
152
153
  #endif /* BACKEND_COMMON_H */
@@ -673,6 +673,67 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE buffer, VALUE length, VALUE pos)
673
673
  return buffer_spec.raw ? INT2FIX(total) : buffer;
674
674
  }
675
675
 
676
+ VALUE Backend_recvmsg(VALUE self, VALUE io, VALUE buffer, VALUE maxlen, VALUE pos, VALUE flags, VALUE maxcontrollen, VALUE opts) {
677
+ Backend_t *backend;
678
+ int fd;
679
+ rb_io_t *fptr;
680
+ struct backend_buffer_spec buffer_spec = backend_get_buffer_spec(buffer, 0);
681
+ long total = 0;
682
+
683
+ GetBackend(self, backend);
684
+ backend_prepare_read_buffer(buffer, maxlen, &buffer_spec, FIX2INT(pos));
685
+ fd = fd_from_io(io, &fptr, 0, 0);
686
+
687
+ char addr_buffer[64];
688
+ struct iovec iov;
689
+ struct msghdr msg;
690
+
691
+ iov.iov_base = StringValuePtr(buffer);
692
+ iov.iov_len = maxlen;
693
+
694
+ msg.msg_name = addr_buffer;
695
+ msg.msg_namelen = sizeof(addr_buffer);
696
+ msg.msg_iov = &iov;
697
+ msg.msg_iovlen = 1;
698
+ msg.msg_control = 0;
699
+ msg.msg_controllen = 0;
700
+ msg.msg_flags = 0;
701
+
702
+ while (1) {
703
+ VALUE resume_value = Qnil;
704
+ op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
705
+ struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
706
+ int result;
707
+ int completed;
708
+
709
+ io_uring_prep_recvmsg(sqe, fd, &msg, NUM2INT(flags));
710
+
711
+ result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
712
+ completed = context_store_release(&backend->store, ctx);
713
+ if (!completed) {
714
+ context_attach_buffers(ctx, 1, &buffer);
715
+ RAISE_IF_EXCEPTION(resume_value);
716
+ return resume_value;
717
+ }
718
+ RB_GC_GUARD(resume_value);
719
+
720
+ if (result < 0)
721
+ rb_syserr_fail(-result, strerror(-result));
722
+ else {
723
+ total += result;
724
+ break;
725
+ }
726
+ }
727
+
728
+ if (!total) return Qnil;
729
+
730
+ if (!buffer_spec.raw) backend_finalize_string_buffer(buffer, &buffer_spec, total, fptr);
731
+ VALUE addr = name_to_addrinfo(msg.msg_name, msg.msg_namelen);
732
+ VALUE rflags = INT2NUM(msg.msg_flags);
733
+ return rb_ary_new_from_args(3, buffer, addr, rflags);
734
+ RB_GC_GUARD(addr);
735
+ }
736
+
676
737
  VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
677
738
  Backend_t *backend;
678
739
  int fd;
@@ -809,6 +870,68 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE buffer, VALUE flags) {
809
870
  return INT2FIX(buffer_spec.len);
810
871
  }
811
872
 
873
+ VALUE Backend_sendmsg(VALUE self, VALUE io, VALUE buffer, VALUE flags, VALUE dest_sockaddr, VALUE controls) {
874
+ Backend_t *backend;
875
+ int fd;
876
+ rb_io_t *fptr;
877
+
878
+ struct backend_buffer_spec buffer_spec = backend_get_buffer_spec(buffer, 1);
879
+ long left = buffer_spec.len;
880
+ int flags_int = FIX2INT(flags);
881
+
882
+ GetBackend(self, backend);
883
+ fd = fd_from_io(io, &fptr, 1, 0);
884
+
885
+ struct iovec iov;
886
+ struct msghdr msg;
887
+
888
+ iov.iov_base = buffer_spec.ptr;
889
+ iov.iov_len = buffer_spec.len;
890
+
891
+ if (dest_sockaddr != Qnil) {
892
+ msg.msg_name = RSTRING_PTR(dest_sockaddr);
893
+ msg.msg_namelen = RSTRING_LEN(dest_sockaddr);
894
+ }
895
+ else {
896
+ msg.msg_name = 0;
897
+ msg.msg_namelen = 0;
898
+ }
899
+ msg.msg_iov = &iov;
900
+ msg.msg_iovlen = 1;
901
+ msg.msg_control = 0;
902
+ msg.msg_controllen = 0;
903
+ msg.msg_flags = 0;
904
+
905
+ while (left > 0) {
906
+ VALUE resume_value = Qnil;
907
+ op_context_t *ctx = context_store_acquire(&backend->store, OP_SEND);
908
+ struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
909
+ int result;
910
+ int completed;
911
+
912
+ io_uring_prep_sendmsg(sqe, fd, &msg, flags_int);
913
+
914
+ result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
915
+ completed = context_store_release(&backend->store, ctx);
916
+ if (!completed) {
917
+ context_attach_buffers(ctx, 1, &buffer);
918
+ RAISE_IF_EXCEPTION(resume_value);
919
+ return resume_value;
920
+ }
921
+ RB_GC_GUARD(resume_value);
922
+
923
+ if (result < 0)
924
+ rb_syserr_fail(-result, strerror(-result));
925
+ else {
926
+ iov.iov_base += result;
927
+ iov.iov_len -= result;
928
+ left -= result;
929
+ }
930
+ }
931
+
932
+ return INT2FIX(buffer_spec.len);
933
+ }
934
+
812
935
  VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE socket_class, int loop) {
813
936
  int server_fd;
814
937
  rb_io_t *server_fptr;
@@ -1727,9 +1850,11 @@ void Init_Backend(void) {
1727
1850
  rb_define_method(cBackend, "read", Backend_read, 5);
1728
1851
  rb_define_method(cBackend, "read_loop", Backend_read_loop, 2);
1729
1852
  rb_define_method(cBackend, "recv", Backend_recv, 4);
1853
+ rb_define_method(cBackend, "recvmsg", Backend_recvmsg, 7);
1730
1854
  rb_define_method(cBackend, "recv_feed_loop", Backend_recv_feed_loop, 3);
1731
1855
  rb_define_method(cBackend, "recv_loop", Backend_recv_loop, 2);
1732
1856
  rb_define_method(cBackend, "send", Backend_send, 3);
1857
+ rb_define_method(cBackend, "sendmsg", Backend_sendmsg, 5);
1733
1858
  rb_define_method(cBackend, "sendv", Backend_sendv, 3);
1734
1859
  rb_define_method(cBackend, "sleep", Backend_sleep, 1);
1735
1860
 
@@ -350,6 +350,72 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE buffer, VALUE length, VALUE pos)
350
350
  return Backend_read(self, io, buffer, length, Qnil, pos);
351
351
  }
352
352
 
353
+ VALUE Backend_recvmsg(VALUE self, VALUE io, VALUE buffer, VALUE maxlen, VALUE pos, VALUE flags, VALUE maxcontrollen, VALUE opts) {
354
+ Backend_t *backend;
355
+ struct libev_io watcher;
356
+ int fd;
357
+ rb_io_t *fptr;
358
+
359
+ struct backend_buffer_spec buffer_spec = backend_get_buffer_spec(buffer, 0);
360
+ long total = 0;
361
+ VALUE switchpoint_result = Qnil;
362
+
363
+ GetBackend(self, backend);
364
+ backend_prepare_read_buffer(buffer, maxlen, &buffer_spec, FIX2INT(pos));
365
+ fd = fd_from_io(io, &fptr, 0, 1);
366
+ watcher.fiber = Qnil;
367
+
368
+ char addr_buffer[64];
369
+ struct iovec iov;
370
+ struct msghdr msg;
371
+
372
+ iov.iov_base = StringValuePtr(buffer);
373
+ iov.iov_len = maxlen;
374
+
375
+ msg.msg_name = addr_buffer;
376
+ msg.msg_namelen = sizeof(addr_buffer);
377
+ msg.msg_iov = &iov;
378
+ msg.msg_iovlen = 1;
379
+ msg.msg_control = 0;
380
+ msg.msg_controllen = 0;
381
+ msg.msg_flags = 0;
382
+
383
+ while (1) {
384
+ backend->base.op_count++;
385
+ ssize_t result = recvmsg(fd, &msg, NUM2INT(flags));
386
+ if (result < 0) {
387
+ int e = errno;
388
+ if (e != EWOULDBLOCK && e != EAGAIN) rb_syserr_fail(e, strerror(e));
389
+
390
+ switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, EV_READ);
391
+
392
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
393
+ }
394
+ else {
395
+ switchpoint_result = backend_snooze(&backend->base);
396
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
397
+
398
+ if (!result) break; // EOF
399
+
400
+ total += result;
401
+ break;
402
+ }
403
+ }
404
+
405
+ if (!total) return Qnil;
406
+
407
+ if (!buffer_spec.raw) backend_finalize_string_buffer(buffer, &buffer_spec, total, fptr);
408
+ VALUE addr = name_to_addrinfo(msg.msg_name, msg.msg_namelen);
409
+ VALUE rflags = INT2NUM(msg.msg_flags);
410
+
411
+ return rb_ary_new_from_args(3, buffer, addr, rflags);
412
+ RB_GC_GUARD(addr);
413
+ RB_GC_GUARD(watcher.fiber);
414
+ RB_GC_GUARD(switchpoint_result);
415
+ error:
416
+ return RAISE_EXCEPTION(switchpoint_result);
417
+ }
418
+
353
419
  VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
354
420
  Backend_t *backend;
355
421
  struct libev_io watcher;
@@ -768,6 +834,73 @@ error:
768
834
  return RAISE_EXCEPTION(switchpoint_result);
769
835
  }
770
836
 
837
+ VALUE Backend_sendmsg(VALUE self, VALUE io, VALUE buffer, VALUE flags, VALUE dest_sockaddr, VALUE controls) {
838
+ Backend_t *backend;
839
+ struct libev_io watcher;
840
+ int fd;
841
+ rb_io_t *fptr;
842
+ VALUE switchpoint_result = Qnil;
843
+
844
+ struct backend_buffer_spec buffer_spec = backend_get_buffer_spec(buffer, 1);
845
+ long left = buffer_spec.len;
846
+ int flags_int = FIX2INT(flags);
847
+
848
+ GetBackend(self, backend);
849
+ fd = fd_from_io(io, &fptr, 1, 0);
850
+ watcher.fiber = Qnil;
851
+
852
+ struct iovec iov;
853
+ struct msghdr msg;
854
+
855
+ iov.iov_base = buffer_spec.ptr;
856
+ iov.iov_len = buffer_spec.len;
857
+
858
+ if (dest_sockaddr != Qnil) {
859
+ msg.msg_name = RSTRING_PTR(dest_sockaddr);
860
+ msg.msg_namelen = RSTRING_LEN(dest_sockaddr);
861
+ }
862
+ else {
863
+ msg.msg_name = 0;
864
+ msg.msg_namelen = 0;
865
+ }
866
+ msg.msg_iov = &iov;
867
+ msg.msg_iovlen = 1;
868
+ msg.msg_control = 0;
869
+ msg.msg_controllen = 0;
870
+ msg.msg_flags = 0;
871
+
872
+ while (left > 0) {
873
+ backend->base.op_count++;
874
+ ssize_t result = sendmsg(fd, &msg, flags_int);
875
+ if (result < 0) {
876
+ int e = errno;
877
+ if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
878
+
879
+ switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, EV_WRITE);
880
+
881
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
882
+ }
883
+ else {
884
+ iov.iov_base = (buffer_spec.ptr += result);
885
+ iov.iov_len -= result;
886
+ left -= result;
887
+ }
888
+ }
889
+
890
+ if (watcher.fiber == Qnil) {
891
+ switchpoint_result = backend_snooze(&backend->base);
892
+
893
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
894
+ }
895
+
896
+ RB_GC_GUARD(watcher.fiber);
897
+ RB_GC_GUARD(switchpoint_result);
898
+
899
+ return INT2FIX(buffer_spec.len);
900
+ error:
901
+ return RAISE_EXCEPTION(switchpoint_result);
902
+ }
903
+
771
904
  struct libev_rw_ctx {
772
905
  int ref_count;
773
906
  VALUE fiber;
@@ -1502,9 +1635,11 @@ void Init_Backend(void) {
1502
1635
  rb_define_method(cBackend, "read", Backend_read, 5);
1503
1636
  rb_define_method(cBackend, "read_loop", Backend_read_loop, 2);
1504
1637
  rb_define_method(cBackend, "recv", Backend_recv, 4);
1638
+ rb_define_method(cBackend, "recvmsg", Backend_recvmsg, 7);
1505
1639
  rb_define_method(cBackend, "recv_loop", Backend_read_loop, 2);
1506
1640
  rb_define_method(cBackend, "recv_feed_loop", Backend_feed_loop, 3);
1507
1641
  rb_define_method(cBackend, "send", Backend_send, 3);
1642
+ rb_define_method(cBackend, "sendmsg", Backend_sendmsg, 5);
1508
1643
  rb_define_method(cBackend, "sendv", Backend_sendv, 3);
1509
1644
  rb_define_method(cBackend, "sleep", Backend_sleep, 1);
1510
1645
 
@@ -55,16 +55,17 @@ if config[:io_uring]
55
55
  else
56
56
  $defs << "-DPOLYPHONY_BACKEND_LIBEV"
57
57
  $defs << "-DPOLYPHONY_LINUX" if config[:linux]
58
- $defs << '-DEV_USE_LINUXAIO' if have_header('linux/aio_abi.h')
59
- $defs << '-DEV_USE_SELECT' if have_header('sys/select.h')
60
- $defs << '-DEV_USE_POLL' if have_type('port_event_t', 'poll.h')
58
+
59
+ $defs << "-DEV_STANDALONE" # prevent libev from assuming "config.h" exists
61
60
  $defs << '-DEV_USE_EPOLL' if have_header('sys/epoll.h')
62
61
  $defs << '-DEV_USE_KQUEUE' if have_header('sys/event.h') && have_header('sys/queue.h')
62
+ $defs << '-DEV_USE_LINUXAIO' if have_header('linux/aio_abi.h')
63
+ $defs << '-DEV_USE_POLL' if have_type('port_event_t', 'poll.h')
63
64
  $defs << '-DEV_USE_PORT' if have_type('port_event_t', 'port.h')
65
+ $defs << '-DEV_USE_SELECT' if have_header('sys/select.h')
66
+
64
67
  $defs << '-DHAVE_SYS_RESOURCE_H' if have_header('sys/resource.h')
65
68
 
66
- $defs << "-DEV_STANDALONE" # prevent libev from assuming "config.h" exists
67
-
68
69
  $CFLAGS << " -Wno-comment"
69
70
  $CFLAGS << " -Wno-unused-result"
70
71
  $CFLAGS << " -Wno-dangling-else"
@@ -21,7 +21,9 @@ ID ID_write;
21
21
 
22
22
  VALUE SYM_backend_read;
23
23
  VALUE SYM_backend_recv;
24
+ VALUE SYM_backend_recvmsg;
24
25
  VALUE SYM_backend_send;
26
+ VALUE SYM_backend_sendmsg;
25
27
  VALUE SYM_backend_write;
26
28
  VALUE SYM_call;
27
29
  VALUE SYM_comment;
@@ -1,5 +1,3 @@
1
- #define EV_STANDALONE
2
-
3
1
  #ifdef POLYPHONY_BACKEND_LIBEV
4
2
 
5
3
  /* keeps ev from requiring config.h */
@@ -66,6 +66,10 @@ VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE buffer, VALUE length, V
66
66
  return Backend_recv(BACKEND(), io, buffer, length, pos);
67
67
  }
68
68
 
69
+ VALUE Polyphony_backend_recvmsg(VALUE self, VALUE io, VALUE buffer, VALUE maxlen, VALUE pos, VALUE flags, VALUE maxcontrollen, VALUE opts) {
70
+ return Backend_recvmsg(BACKEND(), io, buffer, maxlen, pos, flags, maxcontrollen, opts);
71
+ }
72
+
69
73
  VALUE Polyphony_backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
70
74
  return Backend_recv_loop(BACKEND(), io, maxlen);
71
75
  }
@@ -78,6 +82,10 @@ VALUE Polyphony_backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags) {
78
82
  return Backend_send(BACKEND(), io, msg, flags);
79
83
  }
80
84
 
85
+ VALUE Polyphony_backend_sendmsg(VALUE self, VALUE io, VALUE msg, VALUE flags, VALUE dest_sockaddr, VALUE controls) {
86
+ return Backend_sendmsg(BACKEND(), io, msg, flags, dest_sockaddr, controls);
87
+ }
88
+
81
89
  VALUE Polyphony_backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
82
90
  return Backend_sendv(BACKEND(), io, ary, flags);
83
91
  }
@@ -181,9 +189,11 @@ void Init_Polyphony(void) {
181
189
  rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 5);
182
190
  rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 2);
183
191
  rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 4);
192
+ rb_define_singleton_method(mPolyphony, "backend_recvmsg", Polyphony_backend_recvmsg, 7);
184
193
  rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop, 2);
185
194
  rb_define_singleton_method(mPolyphony, "backend_recv_feed_loop", Polyphony_backend_recv_feed_loop, 3);
186
195
  rb_define_singleton_method(mPolyphony, "backend_send", Polyphony_backend_send, 3);
196
+ rb_define_singleton_method(mPolyphony, "backend_sendmsg", Polyphony_backend_sendmsg, 5);
187
197
  rb_define_singleton_method(mPolyphony, "backend_sendv", Polyphony_backend_sendv, 3);
188
198
  rb_define_singleton_method(mPolyphony, "backend_sleep", Polyphony_backend_sleep, 1);
189
199
  rb_define_singleton_method(mPolyphony, "backend_splice", Polyphony_backend_splice, 3);
@@ -100,9 +100,11 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
100
100
  VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos);
101
101
  VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen);
102
102
  VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos);
103
+ VALUE Backend_recvmsg(VALUE self, VALUE io, VALUE buffer, VALUE maxlen, VALUE pos, VALUE flags, VALUE maxcontrollen, VALUE opts);
103
104
  VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen);
104
105
  VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
105
106
  VALUE Backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags);
107
+ VALUE Backend_sendmsg(VALUE self, VALUE io, VALUE msg, VALUE flags, VALUE dest_sockaddr, VALUE controls);
106
108
  VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
107
109
  VALUE Backend_sleep(VALUE self, VALUE duration);
108
110
  VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen);
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'polyphony'
4
-
5
3
  module Kernel
6
4
  alias_method :gets, :orig_gets
7
5
  end
@@ -58,6 +58,58 @@ module Polyphony
58
58
  @holding_fiber
59
59
  end
60
60
 
61
+ # Obtains a lock. Raises `ThreadError` if mutex is locked by the current
62
+ # thread.
63
+ #
64
+ # @return [Mutex] self
65
+ def lock
66
+ raise ThreadError if owned?
67
+
68
+ @token = @store.shift
69
+ @holding_fiber = Fiber.current
70
+ self
71
+ end
72
+
73
+ # Releases the lock. Raises `ThreadError` if mutex is not locked by the
74
+ # current thread.
75
+ #
76
+ # @return [Mutex] self
77
+ def unlock
78
+ raise ThreadError if !owned?
79
+
80
+ @holding_fiber = nil
81
+ @store << @token if @token
82
+ @token = nil
83
+ end
84
+
85
+ # Attempts to obtain the lock and returns immediately. Returns `true` if the
86
+ # lock was granted.
87
+ #
88
+ # @return [true, false]
89
+ def try_lock
90
+ return false if @holding_fiber
91
+
92
+ @token = @store.shift
93
+ @holding_fiber = Fiber.current
94
+ true
95
+ end
96
+
97
+ # Releases the lock and sleeps timeout seconds if it is given and non-nil or
98
+ # forever. Raises `ThreadError` if mutex wasn’t locked by the current
99
+ # thread.
100
+ #
101
+ # @param timeout [nil, Number] sleep timeout
102
+ # @return [Number] slept time in seconds
103
+ def sleep(timeout = nil)
104
+ unlock
105
+ t0 = Time.now
106
+ Kernel.sleep(timeout)
107
+ t1 = Time.now
108
+ lock
109
+
110
+ return t1 - t0
111
+ end
112
+
61
113
  private
62
114
 
63
115
  # Helper method for performing a `#synchronize` when not currently holding
@@ -72,6 +124,7 @@ module Polyphony
72
124
  ensure
73
125
  @holding_fiber = nil
74
126
  @store << @token if @token
127
+ @token = nil
75
128
  end
76
129
  end
77
130
  end
@@ -25,20 +25,19 @@ class ::IO
25
25
 
26
26
  EMPTY_HASH = {}.freeze
27
27
 
28
- # alias_method :orig_foreach, :foreach
29
- # def foreach(_name, _sep = $/, _limit = nil, _getline_args = EMPTY_HASH,
30
- # &_block)
31
- # # IO.orig_read(name).each_line(&block)
32
- # raise NotImplementedError
33
-
34
- # # if sep.is_a?(Integer)
35
- # # sep = $/
36
- # # limit = sep
37
- # # end
38
- # # File.open(name, 'r') do |f|
39
- # # f.each_line(sep, limit, getline_args, &block)
40
- # # end
41
- # end
28
+ alias_method :orig_foreach, :foreach
29
+ def foreach(name, sep = $/, limit = nil, getline_args = EMPTY_HASH, &block)
30
+ # IO.orig_read(name).each_line(&block)
31
+ # raise NotImplementedError
32
+
33
+ if sep.is_a?(Integer)
34
+ sep = $/
35
+ limit = sep
36
+ end
37
+ File.open(name, 'r') do |f|
38
+ f.each_line(sep, limit, chomp: getline_args[:chomp], &block)
39
+ end
40
+ end
42
41
 
43
42
  alias_method :orig_read, :read
44
43
  def read(name, length = nil, offset = nil, opt = EMPTY_HASH)
@@ -143,6 +142,8 @@ class ::IO
143
142
 
144
143
  alias_method :orig_read, :read
145
144
  def read(len = nil, buf = nil, buf_pos = 0)
145
+ return '' if len == 0
146
+
146
147
  if buf
147
148
  return Polyphony.backend_read(self, buf, len, true, buf_pos)
148
149
  end
@@ -196,6 +197,30 @@ class ::IO
196
197
  return nil
197
198
  end
198
199
 
200
+ def each_line(sep = $/, limit = nil, chomp: false)
201
+ if sep.is_a?(Integer)
202
+ limit = sep
203
+ sep = $/
204
+ end
205
+ sep_size = sep.bytesize
206
+
207
+
208
+ @read_buffer ||= +''
209
+
210
+ while true
211
+ while (idx = @read_buffer.index(sep))
212
+ line = @read_buffer.slice!(0, idx + sep_size)
213
+ line = line.chomp if chomp
214
+ yield line
215
+ end
216
+
217
+ result = readpartial(8192, @read_buffer, -1)
218
+ return self if !result
219
+ end
220
+ rescue EOFError
221
+ return self
222
+ end
223
+
199
224
  # def print(*args)
200
225
  # end
201
226
 
@@ -200,7 +200,7 @@ class ::OpenSSL::SSL::SSLServer
200
200
  def accept_loop(ignore_errors = true)
201
201
  loop do
202
202
  yield accept
203
- rescue SystemCallError, StandardError => e
203
+ rescue OpenSSL::SSL::SSLError, SystemCallError => e
204
204
  raise e unless ignore_errors
205
205
  end
206
206
  end