polyphony 0.43.5 → 0.43.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 55e44a81e7358528fabd37e1d48b6387957bc6001e4d947bf6c881d2425953d9
4
- data.tar.gz: 45af7e485891927a1e9f88e8a6342692c25f306aa60e40fa8a74c0ca8494d3d4
3
+ metadata.gz: b048cfa1e0d7cd542840ab9f2198349b2474d40a6d943b584d1bcb57593ca41d
4
+ data.tar.gz: 0d9ed9fc45ec2165018e61f8befbdefb5668cfcf4b7628a648a055f5b6052e4c
5
5
  SHA512:
6
- metadata.gz: 444675baf3131ffc843b61649b92ce5ca7d77773277db750d8c8ac80a88ccd133e6f60d61282fa38ffb91de59eaf2304ea9b0fca196a7eb61c7a53becaa1fe46
7
- data.tar.gz: f21e26a41c8dfeea0d803b5b9bc82b1e648bf0ca588225f721560c432f363020b37561c59daeefbe2d434b012f1f5f767460557939a22d04e78e40471813a8ca
6
+ metadata.gz: a962cb0db032fd58a8db4024d9a6ad2d1be5307caff72d9508bdf879bafbd6c55a5c79e9bc69a9d3bda96d2f72fda51ed2f978e96fa0ca636458284e9e9dbbaf
7
+ data.tar.gz: 2b419313309e898003399f780abcf7641de34c3350ae5d7c10c785209e3e6c12e4d741b01676a49ec1ec2f3f15ea8f9001636ec44880e13583d68168f82c9cb7
@@ -1,3 +1,11 @@
1
+ ## 0.43.6 2020-07-18
2
+
3
+ * Allow brute-force interrupting with second Ctrl-C
4
+ * Fix outgoing SSL connections (#28)
5
+ * Improve Fiber#await_all_children with many children
6
+ * Use `writev` for writing multiple strings
7
+ * Add logo (thanks [Gerald](https://webocube.com/)!)
8
+
1
9
  ## 0.43.5 2020-07-13
2
10
 
3
11
  * Fix `#read_nonblock`, `#write_nonblock` for `IO` and `Socket` (#27)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.43.5)
4
+ polyphony (0.43.6)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ <p align="center"><img src="docs/polyphony-logo.png" /></p>
2
+
1
3
  # Polyphony - Fine-Grained Concurrency for Ruby
2
4
 
3
5
  [![Gem Version](https://badge.fury.io/rb/polyphony.svg)](http://rubygems.org/gems/polyphony)
@@ -0,0 +1,40 @@
1
+ <head>
2
+ <meta charset="UTF-8">
3
+ <meta http-equiv="X-UA-Compatible" content="IE=Edge">
4
+
5
+ {% unless site.plugins contains "jekyll-seo-tag" %}
6
+ <title>{{ page.title }} - {{ site.title }}</title>
7
+
8
+ {% if page.description %}
9
+ <meta name="Description" content="{{ page.description }}">
10
+ {% endif %}
11
+ {% endunless %}
12
+
13
+ <link rel="shortcut icon" href="{{ 'polyphony-logo.png' | absolute_url }}" type="image/png">
14
+
15
+ <link rel="stylesheet" href="{{ '/assets/css/just-the-docs-default.css' | absolute_url }}">
16
+
17
+ {% if site.ga_tracking != nil %}
18
+ <script async src="https://www.googletagmanager.com/gtag/js?id={{ site.ga_tracking }}"></script>
19
+ <script>
20
+ window.dataLayer = window.dataLayer || [];
21
+ function gtag(){dataLayer.push(arguments);}
22
+ gtag('js', new Date());
23
+
24
+ gtag('config', '{{ site.ga_tracking }}'{% unless site.ga_tracking_anonymize_ip == nil %}, { 'anonymize_ip': true }{% endunless %});
25
+ </script>
26
+
27
+ {% endif %}
28
+
29
+ {% if site.search_enabled != false %}
30
+ <script type="text/javascript" src="{{ '/assets/js/vendor/lunr.min.js' | absolute_url }}"></script>
31
+ {% endif %}
32
+ <script type="text/javascript" src="{{ '/assets/js/just-the-docs.js' | absolute_url }}"></script>
33
+
34
+ <meta name="viewport" content="width=device-width, initial-scale=1">
35
+
36
+ {% seo %}
37
+
38
+ {% include head_custom.html %}
39
+
40
+ </head>
@@ -0,0 +1 @@
1
+ <img src="{{ 'polyphony-logo.png' | absolute_url }}" style="height: 1.5em; margin-right: 0.5em">Polyphony
@@ -26,9 +26,9 @@ the entire request body.
26
26
  ## A basic web server
27
27
 
28
28
  ```ruby
29
- require 'polyphony/http'
29
+ require 'tipi'
30
30
 
31
- Polyphony::HTTP::Server.serve('0.0.0.0', 1234) do |request|
31
+ Tipi.serve('0.0.0.0', 1234) do |request|
32
32
  request.respond("Hello world!\n")
33
33
  end
34
34
  ```
@@ -55,13 +55,13 @@ TLS termination can be handled by passing a `secure_context` option to the
55
55
  server:
56
56
 
57
57
  ```ruby
58
- require 'polyphony/http'
58
+ require 'tipi'
59
59
  require 'localhost/authority'
60
60
 
61
61
  authority = Localhost::Authority.fetch
62
62
  opts = { secure_context: authority.server_context }
63
63
 
64
- Polyphony::HTTP::Server.serve('0.0.0.0', 1234, opts) do |request|
64
+ Tipi.serve('0.0.0.0', 1234, opts) do |request|
65
65
  request.respond("Hello world!\n")
66
66
  end
67
67
  ```
@@ -72,8 +72,8 @@ Polyphony's web server makes it really easy to integrate websocket communication
72
72
  with normal HTTP processing:
73
73
 
74
74
  ```ruby
75
- require 'polyphony/http'
76
- require 'polyphony/websocket'
75
+ require 'tipi'
76
+ require 'tipi/websocket'
77
77
 
78
78
  ws_handler = Polyphony::Websocket.handler do |ws|
79
79
  while (msg = ws.recv)
@@ -85,7 +85,7 @@ opts = {
85
85
  upgrade: { websocket: ws_handler }
86
86
  }
87
87
 
88
- Polyphony::HTTP::Server.serve('0.0.0.0', 1234, opts) do |request|
88
+ Tipi.serve('0.0.0.0', 1234, opts) do |request|
89
89
  request.respond("Hello world!\n")
90
90
  end
91
91
  ```
@@ -93,7 +93,7 @@ end
93
93
  Polyphony also supports general-purpose HTTP upgrades using the same mechanism:
94
94
 
95
95
  ```ruby
96
- require 'polyphony/http'
96
+ require 'tipi'
97
97
 
98
98
  opts = {
99
99
  upgrade: {
@@ -105,7 +105,7 @@ opts = {
105
105
  }
106
106
  }
107
107
 
108
- Polyphony::HTTP::Server.serve('0.0.0.0', 1234, opts) do |request|
108
+ Tipi.serve('0.0.0.0', 1234, opts) do |request|
109
109
  request.respond("Hello world!\n")
110
110
  end
111
111
  ```
@@ -117,7 +117,7 @@ and enables streaming (using chunked encoding for HTTP/1.1 connections). Here's
117
117
  an example of an SSE response:
118
118
 
119
119
  ```ruby
120
- require 'polyphony/http'
120
+ require 'tipi'
121
121
 
122
122
  def sse_response(request)
123
123
  request.send_headers('Content-Type': 'text/event-stream')
@@ -131,6 +131,6 @@ ensure
131
131
  request.send_chunk("retry: 0\n\n", done: true)
132
132
  end
133
133
 
134
- Polyphony::HTTP::Server.serve('0.0.0.0', 1234, &method(:sse_response))
134
+ Tipi.serve('0.0.0.0', 1234, &method(:sse_response))
135
135
  ```
136
136
 
@@ -6,6 +6,8 @@ permalink: /
6
6
  next_title: Installing Polyphony
7
7
  ---
8
8
 
9
+ <p align="center"><img src="{{ 'polyphony-logo.png' | absolute_url }}" /></p>
10
+
9
11
  # Polyphony
10
12
  {:.text-center .logo-title}
11
13
 
@@ -21,7 +23,7 @@ for I/O, timers, and other asynchronous events.
21
23
  [Overview](getting-started/overview){: .btn .btn-green .text-gamma }
22
24
  [Take the tutorial](getting-started/tutorial){: .btn .btn-blue .text-gamma }
23
25
  [Source code](https://github.com/digital-fabric/polyphony){: .btn .btn-purple .text-gamma target="_blank" }
24
- {: .mt-6 .h-align-center }
26
+ {:.text-center .mt-6 .h-align-center }
25
27
 
26
28
  ## Focused on Developer Happiness
27
29
 
Binary file
@@ -1,37 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # idea taken from the example given in trio:
4
- # https://www.youtube.com/watch?v=oLkfnc_UMcE
5
-
6
- require 'bundler/setup'
7
3
  require 'polyphony'
8
4
 
9
- def try_connect(target, supervisor)
10
- puts "trying #{target[2]}"
11
- socket = Polyphony::Net.tcp_connect(target[2], 80)
12
- # connection successful
13
- supervisor.stop([target[2], socket])
5
+ def try_connect(ip_address, port, supervisor)
6
+ puts "trying #{ip_address}"
7
+ sleep rand * 0.2
8
+ socket = TCPSocket.new(ip_address, port)
9
+ puts "connected to #{ip_address}"
10
+ supervisor.schedule [ip_address, socket]
14
11
  rescue IOError, SystemCallError
15
12
  # ignore error
16
13
  end
17
14
 
18
- def happy_eyeballs(hostname, port, max_wait_time: 0.025)
15
+ def happy_eyeballs(hostname, port, max_wait_time: 0.010)
19
16
  targets = Socket.getaddrinfo(hostname, port, :INET, :STREAM)
20
17
  t0 = Time.now
21
- cancel_after(5) do
22
- success = supervise do |supervisor|
23
- targets.each_with_index do |t, idx|
24
- sleep(max_wait_time) if idx > 0
25
- supervisor.spin { try_connect(t, supervisor) }
26
- end
27
- end
28
- if success
29
- puts format('success: %s (%.3fs)', success[0], Time.now - t0)
30
- else
31
- puts "timed out (#{Time.now - t0}s)"
18
+ fibers = []
19
+ supervisor = Fiber.current
20
+ spin do
21
+ targets.each do |t|
22
+ spin { try_connect(t[2], t[1], supervisor) }
23
+ sleep(max_wait_time)
32
24
  end
25
+ suspend
26
+ end
27
+ target, socket = move_on_after(5) { suspend }
28
+ supervisor.shutdown_all_children
29
+ if target
30
+ puts format('success: %s (%.3fs)', target, Time.now - t0)
31
+ else
32
+ puts 'timed out'
33
33
  end
34
34
  end
35
35
 
36
- # Let's try it out:
37
36
  happy_eyeballs('debian.org', 'https')
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+ require 'zlib'
6
+
7
+ i, o = IO.pipe
8
+
9
+ w = Zlib::GzipWriter.new(o)
10
+
11
+ s = (1..1000).map { (65 + rand(26)).chr }.join
12
+ puts "full length: #{s.bytesize}"
13
+ w << s
14
+ w.close
15
+ o.close
16
+
17
+
18
+ z = i.read
19
+ puts "zipped length: #{z.bytesize}"
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ puts "pid: #{Process.pid}"
7
+ GC.disable
8
+
9
+ def mem_usage
10
+ # orig_backtick('ps -o rss #{$$}').split.last.to_i
11
+ `ps -o rss #{$$}`.split.last.to_i
12
+ end
13
+
14
+ f = File.open('spin.log', 'w+')
15
+
16
+ m0 = mem_usage
17
+
18
+ X = ARGV[0] ? ARGV[0].to_i : 10
19
+ STDOUT.orig_write "Starting #{X} fibers...\n"
20
+ t0 = Time.now
21
+ x = nil
22
+ X.times do |i|
23
+ spin { p i; suspend }
24
+ end
25
+
26
+ suspend
27
+ f.close
28
+ t1 = Time.now
29
+ m1 = mem_usage
30
+ rate = X / (t1 - t0)
31
+ mem_cost = (m1 - m0) / X.to_f
32
+ STDOUT.orig_write("#{ { time: t1 - t0, spin_rate: rate, fiber_mem_cost: mem_cost }.inspect }\n")
@@ -1,5 +1,6 @@
1
1
  #include <netdb.h>
2
2
  #include <sys/socket.h>
3
+ #include <sys/uio.h>
3
4
 
4
5
  #include "polyphony.h"
5
6
  #include "../libev/ev.h"
@@ -413,20 +414,62 @@ error:
413
414
  return rb_funcall(rb_mKernel, ID_raise, 1, switchpoint_result);
414
415
  }
415
416
 
416
- VALUE LibevAgent_write(int argc, VALUE *argv, VALUE self) {
417
+ VALUE LibevAgent_write(VALUE self, VALUE io, VALUE str) {
417
418
  struct LibevAgent_t *agent;
418
419
  struct libev_io watcher;
419
420
  rb_io_t *fptr;
420
421
  VALUE switchpoint_result = Qnil;
421
- VALUE io;
422
422
  VALUE underlying_io;
423
+ char *buf = StringValuePtr(str);
424
+ long len = RSTRING_LEN(str);
425
+ long left = len;
426
+
427
+ underlying_io = rb_iv_get(io, "@io");
428
+ if (underlying_io != Qnil) io = underlying_io;
429
+ GetLibevAgent(self, agent);
430
+ io = rb_io_get_write_io(io);
431
+ GetOpenFile(io, fptr);
432
+ watcher.fiber = Qnil;
433
+
434
+ while (left > 0) {
435
+ ssize_t n = write(fptr->fd, buf, left);
436
+ if (n < 0) {
437
+ int e = errno;
438
+ if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
439
+ switchpoint_result = libev_io_wait(agent, &watcher, fptr, EV_WRITE);
440
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
441
+ }
442
+ else {
443
+ buf += n;
444
+ left -= n;
445
+ }
446
+ }
447
+
448
+ if (watcher.fiber == Qnil) {
449
+ switchpoint_result = libev_snooze();
450
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
451
+ }
452
+
453
+ RB_GC_GUARD(watcher.fiber);
454
+ RB_GC_GUARD(switchpoint_result);
455
+
456
+ return INT2NUM(len);
457
+ error:
458
+ return rb_funcall(rb_mKernel, ID_raise, 1, switchpoint_result);
459
+ }
460
+
461
+ VALUE LibevAgent_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
462
+ struct LibevAgent_t *agent;
463
+ struct libev_io watcher;
464
+ rb_io_t *fptr;
465
+ VALUE switchpoint_result = Qnil;
466
+ VALUE underlying_io;
467
+ long total_length = 0;
423
468
  long total_written = 0;
424
- int arg_idx = 1;
469
+ struct iovec *iov = 0;
470
+ struct iovec *iov_ptr = 0;
471
+ int iov_count = argc;
425
472
 
426
- if (argc < 2)
427
- rb_raise(rb_eRuntimeError, "(wrong number of arguments (expected 2 or more))");
428
-
429
- io = argv[0];
430
473
  underlying_io = rb_iv_get(io, "@io");
431
474
  if (underlying_io != Qnil) io = underlying_io;
432
475
  GetLibevAgent(self, agent);
@@ -434,30 +477,42 @@ VALUE LibevAgent_write(int argc, VALUE *argv, VALUE self) {
434
477
  GetOpenFile(io, fptr);
435
478
  watcher.fiber = Qnil;
436
479
 
437
- while (arg_idx < argc) {
438
- VALUE str = argv[arg_idx];
439
- char *buf = StringValuePtr(str);
440
- long len = RSTRING_LEN(str);
441
- long left = len;
480
+ iov = malloc(iov_count * sizeof(struct iovec));
481
+ for (int i = 0; i < argc; i++) {
482
+ VALUE str = argv[i];
483
+ iov[i].iov_base = StringValuePtr(str);
484
+ iov[i].iov_len = RSTRING_LEN(str);
485
+ total_length += iov[i].iov_len;
486
+ }
487
+ iov_ptr = iov;
442
488
 
443
- while (left > 0) {
444
- ssize_t n = write(fptr->fd, buf, left);
445
- if (n < 0) {
446
- int e = errno;
447
- if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
489
+ while (1) {
490
+ ssize_t n = writev(fptr->fd, iov_ptr, iov_count);
491
+ if (n < 0) {
492
+ int e = errno;
493
+ if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
448
494
 
449
- switchpoint_result = libev_io_wait(agent, &watcher, fptr, EV_WRITE);
450
- if (TEST_EXCEPTION(switchpoint_result)) goto error;
451
- }
452
- else {
453
- buf += n;
454
- left -= n;
495
+ switchpoint_result = libev_io_wait(agent, &watcher, fptr, EV_WRITE);
496
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
497
+ }
498
+ else {
499
+ total_written += n;
500
+ if (total_written == total_length) break;
501
+
502
+ while (n > 0) {
503
+ if ((size_t) n < iov_ptr[0].iov_len) {
504
+ iov_ptr[0].iov_base = (char *) iov_ptr[0].iov_base + n;
505
+ iov_ptr[0].iov_len -= n;
506
+ n = 0;
507
+ }
508
+ else {
509
+ n -= iov_ptr[0].iov_len;
510
+ iov_ptr += 1;
511
+ iov_count -= 1;
512
+ }
455
513
  }
456
514
  }
457
- total_written += len;
458
- arg_idx++;
459
515
  }
460
-
461
516
  if (watcher.fiber == Qnil) {
462
517
  switchpoint_result = libev_snooze();
463
518
  if (TEST_EXCEPTION(switchpoint_result)) goto error;
@@ -466,11 +521,23 @@ VALUE LibevAgent_write(int argc, VALUE *argv, VALUE self) {
466
521
  RB_GC_GUARD(watcher.fiber);
467
522
  RB_GC_GUARD(switchpoint_result);
468
523
 
524
+ free(iov);
469
525
  return INT2NUM(total_written);
470
526
  error:
527
+ free(iov);
471
528
  return rb_funcall(rb_mKernel, ID_raise, 1, switchpoint_result);
472
529
  }
473
530
 
531
+ VALUE LibevAgent_write_m(int argc, VALUE *argv, VALUE self) {
532
+ if (argc < 2)
533
+ // TODO: raise ArgumentError
534
+ rb_raise(rb_eRuntimeError, "(wrong number of arguments (expected 2 or more))");
535
+
536
+ return (argc == 2) ?
537
+ LibevAgent_write(self, argv[0], argv[1]) :
538
+ LibevAgent_writev(self, argv[0], argc - 1, argv + 1);
539
+ }
540
+
474
541
  ///////////////////////////////////////////////////////////////////////////
475
542
 
476
543
  VALUE LibevAgent_accept(VALUE self, VALUE sock) {
@@ -738,7 +805,7 @@ void Init_LibevAgent() {
738
805
 
739
806
  rb_define_method(cLibevAgent, "read", LibevAgent_read, 4);
740
807
  rb_define_method(cLibevAgent, "read_loop", LibevAgent_read_loop, 1);
741
- rb_define_method(cLibevAgent, "write", LibevAgent_write, -1);
808
+ rb_define_method(cLibevAgent, "write", LibevAgent_write_m, -1);
742
809
  rb_define_method(cLibevAgent, "accept", LibevAgent_accept, 1);
743
810
  rb_define_method(cLibevAgent, "accept_loop", LibevAgent_accept_loop, 1);
744
811
  // rb_define_method(cLibevAgent, "connect", LibevAgent_accept, 3);
@@ -102,7 +102,10 @@ module Polyphony
102
102
 
103
103
  def install_terminating_signal_handlers
104
104
  trap('SIGTERM', SystemExit)
105
- trap('SIGINT', Interrupt)
105
+ orig_trap('SIGINT') do
106
+ orig_trap('SIGINT') { exit! }
107
+ Thread.current.break_out_of_ev_loop(Thread.main.main_fiber, Interrupt.new)
108
+ end
106
109
  end
107
110
 
108
111
  def terminate_threads
@@ -221,14 +221,14 @@ module Polyphony
221
221
  def await_all_children
222
222
  return unless @children && !@children.empty?
223
223
 
224
- # @results = @children.dup
225
- # @on_child_done = proc do |c, r|
226
- # @results[c] = r
227
- # self.schedule if @children.empty?
228
- # end
229
- # suspend
230
- # @results.values
231
- Fiber.await(*@children.keys)
224
+ @results = @children.dup
225
+ @on_child_done = proc do |c, r|
226
+ @results[c] = r
227
+ self.schedule if @children.empty?
228
+ end
229
+ suspend
230
+ @on_child_done = nil
231
+ @results.values
232
232
  end
233
233
 
234
234
  def shutdown_all_children
@@ -5,6 +5,12 @@ require_relative './socket'
5
5
 
6
6
  # Open ssl socket helper methods (to make it compatible with Socket API)
7
7
  class ::OpenSSL::SSL::SSLSocket
8
+ alias_method :orig_initialize, :initialize
9
+ def initialize(socket, context = nil)
10
+ socket = socket.respond_to?(:io) ? socket.io || socket : socket
11
+ context ? orig_initialize(socket, context) : orig_initialize(socket)
12
+ end
13
+
8
14
  def dont_linger
9
15
  io.dont_linger
10
16
  end
@@ -35,6 +41,7 @@ class ::OpenSSL::SSL::SSLSocket
35
41
  loop do
36
42
  case (result = read_nonblock(maxlen, buf, exception: false))
37
43
  when :wait_readable then Thread.current.agent.wait_io(io, false)
44
+ when :wait_writable then Thread.current.agent.wait_io(io, true)
38
45
  else return result
39
46
  end
40
47
  end
@@ -44,6 +51,7 @@ class ::OpenSSL::SSL::SSLSocket
44
51
  def syswrite(buf)
45
52
  loop do
46
53
  case (result = write_nonblock(buf, exception: false))
54
+ when :wait_readable then Thread.current.agent.wait_io(io, false)
47
55
  when :wait_writable then Thread.current.agent.wait_io(io, true)
48
56
  else
49
57
  return result
@@ -87,6 +87,8 @@ end
87
87
  class ::TCPSocket
88
88
  NO_EXCEPTION = { exception: false }.freeze
89
89
 
90
+ attr_reader :io
91
+
90
92
  def initialize(remote_host, remote_port, local_host = nil, local_port = nil)
91
93
  @io = Socket.new Socket::AF_INET, Socket::SOCK_STREAM
92
94
  if local_host && local_port
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.43.5'
4
+ VERSION = '0.43.6'
5
5
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'helper'
4
+ require 'localhost/authority'
4
5
 
5
6
  class SocketTest < MiniTest::Test
6
7
  def setup
@@ -31,4 +32,46 @@ class SocketTest < MiniTest::Test
31
32
  server_fiber&.await
32
33
  server&.close
33
34
  end
35
+
36
+ def test_openssl
37
+ authority = Localhost::Authority.fetch
38
+ context = authority.server_context
39
+ port = rand(1234..5678)
40
+ sock = TCPServer.new('127.0.0.1', port)
41
+ server = OpenSSL::SSL::SSLServer.new(sock, context)
42
+
43
+ server_fiber = spin do
44
+ while (socket = server.accept)
45
+ puts "accepted: #{socket.inspect}"
46
+ spin do
47
+ while (data = socket.gets(8192))
48
+ socket << data
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ snooze
55
+ p 1
56
+ sock = TCPSocket.new('127.0.0.1', port)
57
+ p 2
58
+ sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
59
+ context = OpenSSL::SSL::SSLContext.new
60
+ context.verify_mode = OpenSSL::SSL::VERIFY_NONE
61
+ client = OpenSSL::SSL::SSLSocket.new(sock, context)
62
+ client.sync_close = true
63
+ client.hostname = 'localhost'
64
+ p 3
65
+ client.connect
66
+ p 4
67
+ client.write("GET / HTTP/1.0\r\nHost: realiteq.net\r\n\r\n")#("1234\n")
68
+ p 5
69
+ assert_equal "1234\n", client.readpartial(8192)
70
+ p 6
71
+ client.close
72
+ ensure
73
+ server_fiber&.stop
74
+ server_fiber&.await
75
+ server&.close
76
+ end
34
77
  end
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.43.5
4
+ version: 0.43.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-12 00:00:00.000000000 Z
11
+ date: 2020-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -242,6 +242,8 @@ files:
242
242
  - TODO.md
243
243
  - bin/polyphony-debug
244
244
  - docs/_config.yml
245
+ - docs/_includes/head.html
246
+ - docs/_includes/title.html
245
247
  - docs/_sass/custom/custom.scss
246
248
  - docs/_sass/overrides.scss
247
249
  - docs/_user-guide/all-about-timers.md
@@ -351,6 +353,7 @@ files:
351
353
  - examples/io/xx-system.rb
352
354
  - examples/io/xx-tcpserver.rb
353
355
  - examples/io/xx-tcpsocket.rb
356
+ - examples/io/xx-zip.rb
354
357
  - examples/performance/fs_read.rb
355
358
  - examples/performance/mem-usage.rb
356
359
  - examples/performance/messaging.rb
@@ -367,6 +370,7 @@ files:
367
370
  - examples/performance/xx-array.rb
368
371
  - examples/performance/xx-fiber-switch.rb
369
372
  - examples/performance/xx-snooze.rb
373
+ - examples/xx-spin.rb
370
374
  - ext/libev/Changes
371
375
  - ext/libev/LICENSE
372
376
  - ext/libev/README