polyphony 0.97 → 0.98
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/examples/io/irb.rb +1 -1
- data/ext/polyphony/backend_common.c +30 -0
- data/ext/polyphony/backend_common.h +1 -0
- data/ext/polyphony/backend_io_uring.c +125 -0
- data/ext/polyphony/backend_libev.c +135 -0
- data/ext/polyphony/io_extensions.c +2 -0
- data/ext/polyphony/polyphony.c +10 -0
- data/ext/polyphony/polyphony.h +2 -0
- data/lib/polyphony/adapters/irb.rb +0 -2
- data/lib/polyphony/extensions/io.rb +2 -0
- data/lib/polyphony/extensions/socket.rb +30 -1
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +4 -0
- data/test/test_io.rb +8 -0
- data/test/test_socket.rb +70 -10
- data/test/test_thread.rb +2 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf93e3d5dfd0a5e3a4a70ee66d62caddc1ea22e63cf1ce44a212a75f18c2ac76
|
4
|
+
data.tar.gz: 121f84bb920ccc6822cb43b772a68dd92b2f2d81ebf9e1a510c081481dd1e3b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 286d3cb30ecd19b8f046fe43761f6d2f243f3e3a8134d01ebe14fdfdf11d6d879000f51ba66c705b0ad425e3c6a51dff02781b47e8cf75e52bc4f0439dfffc0e
|
7
|
+
data.tar.gz: 7caf9e3b7294ece38c964dc0366011b07d8977f95ec8c92a22763b9ecccc33080de40b5ab19bb66223eb4bb27be0847c92879a173dceee1b3fda9e1b03b0cdcd
|
data/CHANGELOG.md
CHANGED
data/examples/io/irb.rb
CHANGED
@@ -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
|
|
data/ext/polyphony/polyphony.c
CHANGED
@@ -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);
|
data/ext/polyphony/polyphony.h
CHANGED
@@ -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);
|
@@ -742,4 +742,33 @@ class ::UNIXSocket
|
|
742
742
|
def write_nonblock(buf, exception: true)
|
743
743
|
@io.write_nonblock(buf, exception: exception)
|
744
744
|
end
|
745
|
-
end
|
745
|
+
end
|
746
|
+
|
747
|
+
class ::UDPSocket
|
748
|
+
def recvfrom(maxlen, flags = 0)
|
749
|
+
buf = +''
|
750
|
+
Polyphony.backend_recvmsg(self, buf, maxlen, 0, flags, 0, nil)
|
751
|
+
end
|
752
|
+
|
753
|
+
def recvmsg(maxlen = nil, flags = 0, maxcontrollen = nil, opts = {})
|
754
|
+
buf = +''
|
755
|
+
Polyphony.backend_recvmsg(self, buf, maxlen || 4096, 0, flags, maxcontrollen, opts)
|
756
|
+
end
|
757
|
+
|
758
|
+
def sendmsg(msg, flags = 0, dest_sockaddr = nil, *controls)
|
759
|
+
Polyphony.backend_sendmsg(self, msg, flags, dest_sockaddr, controls)
|
760
|
+
end
|
761
|
+
|
762
|
+
def send(msg, flags, *addr)
|
763
|
+
sockaddr = case addr.size
|
764
|
+
when 2
|
765
|
+
Socket.sockaddr_in(addr[1], addr[0])
|
766
|
+
when 1
|
767
|
+
addr[0]
|
768
|
+
else
|
769
|
+
nil
|
770
|
+
end
|
771
|
+
|
772
|
+
Polyphony.backend_sendmsg(self, msg, flags, sockaddr, nil)
|
773
|
+
end
|
774
|
+
end
|
data/lib/polyphony/version.rb
CHANGED
data/lib/polyphony.rb
CHANGED
data/test/test_io.rb
CHANGED
@@ -93,6 +93,13 @@ class IOTest < MiniTest::Test
|
|
93
93
|
assert_equal 'deffoobar', buf
|
94
94
|
end
|
95
95
|
|
96
|
+
def test_read_zero
|
97
|
+
i, o = IO.pipe
|
98
|
+
|
99
|
+
o << 'hi'
|
100
|
+
assert_equal '', i.read(0)
|
101
|
+
end
|
102
|
+
|
96
103
|
def test_readpartial
|
97
104
|
i, o = IO.pipe
|
98
105
|
|
@@ -658,6 +665,7 @@ class IOClassMethodsTest < MiniTest::Test
|
|
658
665
|
|
659
666
|
# writing always causes snoozing
|
660
667
|
o << 'foo'
|
668
|
+
3.times { snooze }
|
661
669
|
o << 'bar'
|
662
670
|
o.close
|
663
671
|
|
data/test/test_socket.rb
CHANGED
@@ -4,11 +4,7 @@ require_relative 'helper'
|
|
4
4
|
require 'fileutils'
|
5
5
|
require 'msgpack'
|
6
6
|
|
7
|
-
class
|
8
|
-
def setup
|
9
|
-
super
|
10
|
-
end
|
11
|
-
|
7
|
+
class TCPSocketTest < MiniTest::Test
|
12
8
|
def start_tcp_server_on_random_port(host = '127.0.0.1')
|
13
9
|
port = rand(1100..60000)
|
14
10
|
server = TCPServer.new(host, port)
|
@@ -41,13 +37,13 @@ class SocketTest < MiniTest::Test
|
|
41
37
|
end
|
42
38
|
|
43
39
|
def test_tcpsocket_open_with_hostname
|
44
|
-
client = TCPSocket.open('
|
45
|
-
client.write("GET / HTTP/1.0\r\nHost:
|
40
|
+
client = TCPSocket.open('ipinfo.io', 80)
|
41
|
+
client.write("GET / HTTP/1.0\r\nHost: ipinfo.io\r\n\r\n")
|
46
42
|
result = nil
|
47
43
|
move_on_after(3) {
|
48
44
|
result = client.read
|
49
45
|
}
|
50
|
-
assert result =~ /HTTP\/1.0
|
46
|
+
assert result =~ /HTTP\/1.0 200 OK/
|
51
47
|
end
|
52
48
|
|
53
49
|
def test_tcp_ipv6
|
@@ -166,7 +162,9 @@ class SocketTest < MiniTest::Test
|
|
166
162
|
server_fiber&.await
|
167
163
|
server&.close
|
168
164
|
end
|
165
|
+
end
|
169
166
|
|
167
|
+
class UNIXSocketTest < MiniTest::Test
|
170
168
|
def test_unix_socket
|
171
169
|
path = '/tmp/test_unix_socket'
|
172
170
|
FileUtils.rm(path) rescue nil
|
@@ -193,7 +191,7 @@ class SocketTest < MiniTest::Test
|
|
193
191
|
end
|
194
192
|
end
|
195
193
|
|
196
|
-
class
|
194
|
+
class TCPSocketWithRawBufferTest < MiniTest::Test
|
197
195
|
def start_tcp_server_on_random_port(host = '127.0.0.1')
|
198
196
|
port = rand(1100..60000)
|
199
197
|
server = TCPServer.new(host, port)
|
@@ -243,6 +241,68 @@ class SocketWithRawBufferTest < MiniTest::Test
|
|
243
241
|
end
|
244
242
|
end
|
245
243
|
|
244
|
+
class UDPSocketTest < MiniTest::Test
|
245
|
+
def test_udp_recvfrom
|
246
|
+
u1 = UDPSocket.new
|
247
|
+
u1.bind('127.0.0.1', 0)
|
248
|
+
|
249
|
+
server_fiber = spin do
|
250
|
+
msg, peer_addr = u1.recvfrom(256)
|
251
|
+
u1.send(msg, 0, peer_addr[3], peer_addr[1])
|
252
|
+
end
|
253
|
+
|
254
|
+
server_addr = u1.addr
|
255
|
+
u2 = UDPSocket.new
|
256
|
+
u2.bind('127.0.0.1', 0)
|
257
|
+
u2.send('foobar', 0, server_addr[3], server_addr[1])
|
258
|
+
|
259
|
+
msg, addr = u2.recvfrom(256)
|
260
|
+
|
261
|
+
assert_equal 'foobar', msg
|
262
|
+
assert_equal server_addr, addr
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_udp_recvmsg
|
266
|
+
u1 = UDPSocket.new
|
267
|
+
u1.bind('127.0.0.1', 0)
|
268
|
+
|
269
|
+
server_fiber = spin do
|
270
|
+
msg, peer_addr = u1.recvmsg(256)
|
271
|
+
u1.send(msg, 0, peer_addr[3], peer_addr[1])
|
272
|
+
end
|
273
|
+
|
274
|
+
server_addr = u1.addr
|
275
|
+
u2 = UDPSocket.new
|
276
|
+
u2.bind('127.0.0.1', 0)
|
277
|
+
u2.send('foobar', 0, server_addr[3], server_addr[1])
|
278
|
+
|
279
|
+
msg, addr = u2.recvmsg(256)
|
280
|
+
|
281
|
+
assert_equal 'foobar', msg
|
282
|
+
assert_equal server_addr, addr
|
283
|
+
end
|
284
|
+
|
285
|
+
def test_udp_recvfrom_ipv6
|
286
|
+
u1 = UDPSocket.new :INET6
|
287
|
+
u1.bind('::1', 0)
|
288
|
+
|
289
|
+
server_fiber = spin do
|
290
|
+
msg, peer_addr = u1.recvfrom(256)
|
291
|
+
u1.send(msg, 0, peer_addr[3], peer_addr[1])
|
292
|
+
end
|
293
|
+
|
294
|
+
server_addr = u1.addr
|
295
|
+
u2 = UDPSocket.new :INET6
|
296
|
+
u2.bind('::1', 0)
|
297
|
+
u2.send('foobar', 0, server_addr[3], server_addr[1])
|
298
|
+
|
299
|
+
msg, addr = u2.recvfrom(256)
|
300
|
+
|
301
|
+
assert_equal 'foobar', msg
|
302
|
+
assert_equal server_addr, addr
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
246
306
|
if IS_LINUX
|
247
307
|
class HTTPClientTest < MiniTest::Test
|
248
308
|
|
@@ -261,4 +321,4 @@ if IS_LINUX
|
|
261
321
|
assert_equal 'https://ipinfo.io/missingauth', response['readme']
|
262
322
|
end
|
263
323
|
end
|
264
|
-
end
|
324
|
+
end
|
data/test/test_thread.rb
CHANGED
@@ -40,13 +40,14 @@ class ThreadTest < MiniTest::Test
|
|
40
40
|
|
41
41
|
def test_thread_join_with_timeout
|
42
42
|
buffer = []
|
43
|
-
spin { (1..3).each { |i| snooze; buffer << i } }
|
43
|
+
f = spin { (1..3).each { |i| snooze; buffer << i } }
|
44
44
|
t = Thread.new { sleep 1; buffer << 4 }
|
45
45
|
t0 = Time.now
|
46
46
|
r = t.join(0.01)
|
47
47
|
t = nil
|
48
48
|
|
49
49
|
assert Time.now - t0 < 0.2
|
50
|
+
f.join
|
50
51
|
assert_equal [1, 2, 3], buffer
|
51
52
|
assert_nil r
|
52
53
|
ensure
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: polyphony
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.98'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|