tttls1.3 0.3.0 → 0.3.2
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/.github/workflows/ci.yml +2 -2
- data/.rubocop.yml +3 -0
- data/.ruby-version +1 -1
- data/Gemfile +1 -0
- data/README.md +2 -2
- data/example/README.md +1 -1
- data/example/helper.rb +22 -0
- data/example/https_client.rb +4 -4
- data/example/https_client_using_0rtt.rb +6 -5
- data/example/https_client_using_ech.rb +5 -6
- data/example/https_client_using_grease_ech.rb +3 -5
- data/example/https_client_using_grease_psk.rb +8 -16
- data/example/https_client_using_hrr.rb +5 -4
- data/example/https_client_using_hrr_and_ech.rb +6 -6
- data/example/https_client_using_hrr_and_ticket.rb +5 -4
- data/example/https_client_using_status_request.rb +4 -5
- data/example/https_client_using_ticket.rb +5 -4
- data/example/https_server.rb +14 -1
- data/lib/tttls1.3/client.rb +205 -418
- data/lib/tttls1.3/connection.rb +21 -362
- data/lib/tttls1.3/ech.rb +410 -0
- data/lib/tttls1.3/endpoint.rb +276 -0
- data/lib/tttls1.3/message/certificate_verify.rb +1 -1
- data/lib/tttls1.3/message/extension/ech.rb +12 -10
- data/lib/tttls1.3/message/extension/signature_algorithms.rb +2 -2
- data/lib/tttls1.3/message/extension/supported_versions.rb +3 -3
- data/lib/tttls1.3/message/extension/unknown_extension.rb +2 -2
- data/lib/tttls1.3/server.rb +125 -63
- data/lib/tttls1.3/utils.rb +37 -0
- data/lib/tttls1.3/version.rb +1 -1
- data/lib/tttls1.3.rb +2 -1
- data/spec/client_spec.rb +21 -60
- data/spec/ech_spec.rb +39 -0
- data/spec/{connection_spec.rb → endpoint_spec.rb} +41 -49
- data/spec/server_spec.rb +12 -12
- data/tttls1.3.gemspec +1 -1
- metadata +8 -7
- data/lib/tttls1.3/hpke.rb +0 -91
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7245602faa9087e83b3e47484aa88dc368b153e98c76fd00e36ebb1a863af6ef
|
4
|
+
data.tar.gz: c7362f39fc26763f712cdf61a29b3796686c50034d2a6431788d8dbf7dd505c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33168ef27007f9e6d73197ed3e1bae9b58dadfdf3042e732ddc6a05913db0aad48fb653ea7b7222716d70ebe42739f2d9dddee0ec75ee45eb33daba4be6f0229
|
7
|
+
data.tar.gz: d05c73a49e0f5d568785c3b6af3d9bc3c286b35f1110c5f31860f8cf788a9f9e019112fd8647394672c279808e20c4f02d438a58c44f5bab9af1d5fb851ef41f
|
data/.github/workflows/ci.yml
CHANGED
@@ -13,14 +13,14 @@ jobs:
|
|
13
13
|
runs-on: ubuntu-latest
|
14
14
|
strategy:
|
15
15
|
matrix:
|
16
|
-
ruby-version: ['
|
16
|
+
ruby-version: ['3.1', '3.2', '3.3']
|
17
17
|
steps:
|
18
18
|
- uses: actions/checkout@v3
|
19
19
|
- uses: docker://thekuwayama/openssl:latest
|
20
20
|
- name: Set up Ruby
|
21
21
|
uses: ruby/setup-ruby@v1
|
22
22
|
with:
|
23
|
-
ruby-version: ${{ matrix.ruby }}
|
23
|
+
ruby-version: ${{ matrix.ruby-version }}
|
24
24
|
- name: Install dependencies
|
25
25
|
run: |
|
26
26
|
gem --version
|
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.2.2
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -104,8 +104,8 @@ tttls1.3 client is configurable using keyword arguments.
|
|
104
104
|
| `:check_certificate_status` | Boolean | false | If needed to check certificate status, set true. |
|
105
105
|
| `:process_certificate_status` | Proc | `TTTLS13::Client.method(:softfail_check_certificate_status)` | Proc(or Method) that checks received OCSPResponse. Its 3 arguments are OpenSSL::OCSP::Response, end-entity certificate(OpenSSL::X509::Certificate) and certificates chain(Array of Certificate) used for verification and it returns Boolean. |
|
106
106
|
| `:compress_certificate_algorithms` | Array of TTTLS13::Message::Extension::CertificateCompressionAlgorithm constant | `ZLIB` | The compression algorithms are supported for compressing the Certificate message. |
|
107
|
-
| `:ech_config` | ECHConfig | nil | ECHConfig to use ECH.
|
108
|
-
| `:ech_hpke_cipher_suites` | Array of ECHConfig::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite | nil | If needed to use ECH, set client preference HPKE cipher suites. |
|
107
|
+
| `:ech_config` | ECHConfig | nil | ECHConfig to use ECH. See [ech_config](https://github.com/thekuwayama/ech_config). |
|
108
|
+
| `:ech_hpke_cipher_suites` | Array of ECHConfig::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite | nil | If needed to use ECH, set client preference HPKE cipher suites. For example, you can set TTTLS13::STANDARD\_CLIENT\_ECH_HPKE\_SYMMETRIC\_CIPHER\_SUITES. |
|
109
109
|
| `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
|
110
110
|
| `:sslkeylogfile` | String | nil | If needed to log SSLKEYLOGFILE, set the file path. |
|
111
111
|
| `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
|
data/example/README.md
CHANGED
data/example/helper.rb
CHANGED
@@ -4,6 +4,7 @@ $LOAD_PATH << __dir__ + '/../lib'
|
|
4
4
|
|
5
5
|
require 'socket'
|
6
6
|
require 'time'
|
7
|
+
require 'uri'
|
7
8
|
require 'webrick'
|
8
9
|
|
9
10
|
require 'http/parser'
|
@@ -61,3 +62,24 @@ def recv_http_response(client)
|
|
61
62
|
parser << client.read until client.eof?
|
62
63
|
buf
|
63
64
|
end
|
65
|
+
|
66
|
+
def transcript_htmlize(transcript)
|
67
|
+
m = {
|
68
|
+
TTTLS13::CH1 => 'ClientHello',
|
69
|
+
TTTLS13::HRR => 'HelloRetryRequest',
|
70
|
+
TTTLS13::CH => 'ClientHello',
|
71
|
+
TTTLS13::SH => 'ServerHello',
|
72
|
+
TTTLS13::EE => 'EncryptedExtensions',
|
73
|
+
TTTLS13::CR => 'CertificateRequest',
|
74
|
+
TTTLS13::CT => 'Certificate',
|
75
|
+
TTTLS13::CV => 'CertificateVerify',
|
76
|
+
TTTLS13::SF => 'Finished',
|
77
|
+
TTTLS13::EOED => 'EndOfEarlyData',
|
78
|
+
TTTLS13::CCT => 'Certificate',
|
79
|
+
TTTLS13::CCV => 'CertificateVerify',
|
80
|
+
TTTLS13::CF => 'Finished'
|
81
|
+
}.map { |k, v| [k, '<details><summary>' + v + '</summary>%s</details>'] }.to_h
|
82
|
+
transcript.map do |k, v|
|
83
|
+
format(m[k], TTTLS13::Convert.obj2html(v.first))
|
84
|
+
end.join('<br>')
|
85
|
+
end
|
data/example/https_client.rb
CHANGED
@@ -3,17 +3,17 @@
|
|
3
3
|
|
4
4
|
require_relative 'helper'
|
5
5
|
|
6
|
-
|
6
|
+
uri = URI.parse(ARGV[0] || 'https://localhost:4433')
|
7
7
|
ca_file = __dir__ + '/../tmp/ca.crt'
|
8
|
-
req = simple_http_request(
|
8
|
+
req = simple_http_request(uri.host, uri.path)
|
9
9
|
|
10
|
-
socket = TCPSocket.new(
|
10
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
11
11
|
settings = {
|
12
12
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
13
13
|
alpn: ['http/1.1'],
|
14
14
|
sslkeylogfile: '/tmp/sslkeylogfile.log'
|
15
15
|
}
|
16
|
-
client = TTTLS13::Client.new(socket,
|
16
|
+
client = TTTLS13::Client.new(socket, uri.host, **settings)
|
17
17
|
client.connect
|
18
18
|
client.write(req)
|
19
19
|
|
@@ -3,9 +3,9 @@
|
|
3
3
|
|
4
4
|
require_relative 'helper'
|
5
5
|
|
6
|
-
|
6
|
+
uri = URI.parse(ARGV[0] || 'https://localhost:4433')
|
7
7
|
ca_file = __dir__ + '/../tmp/ca.crt'
|
8
|
-
req = simple_http_request(
|
8
|
+
req = simple_http_request(uri.host, uri.path)
|
9
9
|
|
10
10
|
settings_2nd = {
|
11
11
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
@@ -15,7 +15,7 @@ process_new_session_ticket = lambda do |nst, rms, cs|
|
|
15
15
|
return if Time.now.to_i - nst.timestamp > nst.ticket_lifetime
|
16
16
|
|
17
17
|
settings_2nd[:ticket] = nst.ticket
|
18
|
-
settings_2nd[:
|
18
|
+
settings_2nd[:resumption_secret] = rms
|
19
19
|
settings_2nd[:psk_cipher_suite] = cs
|
20
20
|
settings_2nd[:ticket_nonce] = nst.ticket_nonce
|
21
21
|
settings_2nd[:ticket_age_add] = nst.ticket_age_add
|
@@ -35,14 +35,15 @@ succeed_early_data = false
|
|
35
35
|
# Subsequent Handshake:
|
36
36
|
settings_2nd
|
37
37
|
].each_with_index do |settings, i|
|
38
|
-
socket = TCPSocket.new(
|
39
|
-
client = TTTLS13::Client.new(socket,
|
38
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
39
|
+
client = TTTLS13::Client.new(socket, uri.host, **settings)
|
40
40
|
|
41
41
|
# send message using early data; 0-RTT
|
42
42
|
client.early_data(req) if i == 1 && settings.include?(:ticket)
|
43
43
|
client.connect
|
44
44
|
# send message after Simple 1-RTT Handshake
|
45
45
|
client.write(req) if i.zero? || !client.succeed_early_data?
|
46
|
+
|
46
47
|
print recv_http_response(client)
|
47
48
|
client.close unless client.eof?
|
48
49
|
socket.close
|
@@ -5,16 +5,15 @@ require_relative 'helper'
|
|
5
5
|
HpkeSymmetricCipherSuite = \
|
6
6
|
ECHConfig::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite
|
7
7
|
|
8
|
-
|
9
|
-
port = 443
|
8
|
+
uri = URI.parse(ARGV[0] || 'https://localhost:4433')
|
10
9
|
ca_file = __dir__ + '/../tmp/ca.crt'
|
11
|
-
req = simple_http_request(
|
10
|
+
req = simple_http_request(uri.host, uri.path)
|
12
11
|
|
13
12
|
rr = Resolv::DNS.new.getresources(
|
14
|
-
|
13
|
+
uri.host,
|
15
14
|
Resolv::DNS::Resource::IN::HTTPS
|
16
15
|
)
|
17
|
-
socket = TCPSocket.new(
|
16
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
18
17
|
settings = {
|
19
18
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
20
19
|
alpn: ['http/1.1'],
|
@@ -23,7 +22,7 @@ settings = {
|
|
23
22
|
TTTLS13::STANDARD_CLIENT_ECH_HPKE_SYMMETRIC_CIPHER_SUITES,
|
24
23
|
sslkeylogfile: '/tmp/sslkeylogfile.log'
|
25
24
|
}
|
26
|
-
client = TTTLS13::Client.new(socket,
|
25
|
+
client = TTTLS13::Client.new(socket, uri.host, **settings)
|
27
26
|
client.connect
|
28
27
|
client.write(req)
|
29
28
|
|
@@ -5,11 +5,10 @@ require_relative 'helper'
|
|
5
5
|
HpkeSymmetricCipherSuite = \
|
6
6
|
ECHConfig::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite
|
7
7
|
|
8
|
-
|
9
|
-
port = 443
|
8
|
+
uri = URI.parse(ARGV[0] || 'https://localhost:4433')
|
10
9
|
ca_file = __dir__ + '/../tmp/ca.crt'
|
11
10
|
|
12
|
-
socket = TCPSocket.new(
|
11
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
13
12
|
settings = {
|
14
13
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
15
14
|
alpn: ['http/1.1'],
|
@@ -17,10 +16,9 @@ settings = {
|
|
17
16
|
TTTLS13::STANDARD_CLIENT_ECH_HPKE_SYMMETRIC_CIPHER_SUITES,
|
18
17
|
sslkeylogfile: '/tmp/sslkeylogfile.log'
|
19
18
|
}
|
20
|
-
client = TTTLS13::Client.new(socket,
|
19
|
+
client = TTTLS13::Client.new(socket, uri.host, **settings)
|
21
20
|
client.connect
|
22
21
|
|
23
22
|
print client.retry_configs if client.rejected_ech?
|
24
|
-
|
25
23
|
client.close unless client.eof?
|
26
24
|
socket.close
|
@@ -5,13 +5,12 @@ require_relative 'helper'
|
|
5
5
|
HpkeSymmetricCipherSuite = \
|
6
6
|
ECHConfig::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite
|
7
7
|
|
8
|
-
|
9
|
-
port = 443
|
8
|
+
uri = URI.parse(ARGV[0] || 'https://localhost:4433')
|
10
9
|
ca_file = __dir__ + '/../tmp/ca.crt'
|
11
|
-
req = simple_http_request(
|
10
|
+
req = simple_http_request(uri.host, uri.path)
|
12
11
|
|
13
12
|
rr = Resolv::DNS.new.getresources(
|
14
|
-
|
13
|
+
uri.host,
|
15
14
|
Resolv::DNS::Resource::IN::HTTPS
|
16
15
|
)
|
17
16
|
settings_2nd = {
|
@@ -37,16 +36,8 @@ settings_1st = {
|
|
37
36
|
alpn: ['http/1.1'],
|
38
37
|
process_new_session_ticket: process_new_session_ticket,
|
39
38
|
ech_config: rr.first.svc_params['ech'].echconfiglist.first,
|
40
|
-
ech_hpke_cipher_suites:
|
41
|
-
|
42
|
-
HpkeSymmetricCipherSuite::HpkeKdfId.new(
|
43
|
-
TTTLS13::Hpke::KdfId::HKDF_SHA256
|
44
|
-
),
|
45
|
-
HpkeSymmetricCipherSuite::HpkeAeadId.new(
|
46
|
-
TTTLS13::Hpke::AeadId::AES_128_GCM
|
47
|
-
)
|
48
|
-
)
|
49
|
-
],
|
39
|
+
ech_hpke_cipher_suites:
|
40
|
+
TTTLS13::STANDARD_CLIENT_ECH_HPKE_SYMMETRIC_CIPHER_SUITES,
|
50
41
|
sslkeylogfile: '/tmp/sslkeylogfile.log'
|
51
42
|
}
|
52
43
|
|
@@ -56,10 +47,11 @@ settings_1st = {
|
|
56
47
|
# Subsequent Handshake:
|
57
48
|
settings_2nd
|
58
49
|
].each do |settings|
|
59
|
-
socket = TCPSocket.new(
|
60
|
-
client = TTTLS13::Client.new(socket,
|
50
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
51
|
+
client = TTTLS13::Client.new(socket, uri.host, **settings)
|
61
52
|
client.connect
|
62
53
|
client.write(req)
|
54
|
+
|
63
55
|
print recv_http_response(client)
|
64
56
|
client.close unless client.eof?
|
65
57
|
socket.close
|
@@ -3,19 +3,20 @@
|
|
3
3
|
|
4
4
|
require_relative 'helper'
|
5
5
|
|
6
|
-
|
6
|
+
uri = URI.parse(ARGV[0] || 'https://localhost:4433')
|
7
7
|
ca_file = __dir__ + '/../tmp/ca.crt'
|
8
|
-
req = simple_http_request(
|
8
|
+
req = simple_http_request(uri.host, uri.path)
|
9
9
|
|
10
|
-
socket = TCPSocket.new(
|
10
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
11
11
|
settings = {
|
12
12
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
13
13
|
key_share_groups: [], # empty KeyShareClientHello.client_shares
|
14
14
|
alpn: ['http/1.1']
|
15
15
|
}
|
16
|
-
client = TTTLS13::Client.new(socket,
|
16
|
+
client = TTTLS13::Client.new(socket, uri.host, **settings)
|
17
17
|
client.connect
|
18
18
|
client.write(req)
|
19
|
+
|
19
20
|
print recv_http_response(client)
|
20
21
|
client.close unless client.eof?
|
21
22
|
socket.close
|
@@ -5,16 +5,15 @@ require_relative 'helper'
|
|
5
5
|
HpkeSymmetricCipherSuite = \
|
6
6
|
ECHConfig::ECHConfigContents::HpkeKeyConfig::HpkeSymmetricCipherSuite
|
7
7
|
|
8
|
-
|
9
|
-
port = 443
|
8
|
+
uri = URI.parse(ARGV[0] || 'https://localhost:4433')
|
10
9
|
ca_file = __dir__ + '/../tmp/ca.crt'
|
11
|
-
req = simple_http_request(
|
10
|
+
req = simple_http_request(uri.host, uri.path)
|
12
11
|
|
13
12
|
rr = Resolv::DNS.new.getresources(
|
14
|
-
|
13
|
+
uri.host,
|
15
14
|
Resolv::DNS::Resource::IN::HTTPS
|
16
15
|
)
|
17
|
-
socket = TCPSocket.new(
|
16
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
18
17
|
settings = {
|
19
18
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
20
19
|
key_share_groups: [], # empty KeyShareClientHello.client_shares
|
@@ -24,9 +23,10 @@ settings = {
|
|
24
23
|
TTTLS13::STANDARD_CLIENT_ECH_HPKE_SYMMETRIC_CIPHER_SUITES,
|
25
24
|
sslkeylogfile: '/tmp/sslkeylogfile.log'
|
26
25
|
}
|
27
|
-
client = TTTLS13::Client.new(socket,
|
26
|
+
client = TTTLS13::Client.new(socket, uri.host, **settings)
|
28
27
|
client.connect
|
29
28
|
client.write(req)
|
29
|
+
|
30
30
|
print recv_http_response(client)
|
31
31
|
client.close unless client.eof?
|
32
32
|
socket.close
|
@@ -3,9 +3,9 @@
|
|
3
3
|
|
4
4
|
require_relative 'helper'
|
5
5
|
|
6
|
-
|
6
|
+
uri = URI.parse(ARGV[0] || 'https://localhost:4433')
|
7
7
|
ca_file = __dir__ + '/../tmp/ca.crt'
|
8
|
-
req = simple_http_request(
|
8
|
+
req = simple_http_request(uri.host, uri.path)
|
9
9
|
|
10
10
|
settings_2nd = {
|
11
11
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
@@ -34,10 +34,11 @@ settings_1st = {
|
|
34
34
|
# Subsequent Handshake:
|
35
35
|
settings_2nd
|
36
36
|
].each do |settings|
|
37
|
-
socket = TCPSocket.new(
|
38
|
-
client = TTTLS13::Client.new(socket,
|
37
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
38
|
+
client = TTTLS13::Client.new(socket, uri.host, **settings)
|
39
39
|
client.connect
|
40
40
|
client.write(req)
|
41
|
+
|
41
42
|
print recv_http_response(client)
|
42
43
|
client.close unless client.eof?
|
43
44
|
socket.close
|
@@ -3,10 +3,11 @@
|
|
3
3
|
|
4
4
|
require_relative 'helper'
|
5
5
|
|
6
|
-
|
6
|
+
uri = URI.parse(ARGV[0] || 'https://localhost:4433')
|
7
7
|
ca_file = __dir__ + '/../tmp/ca.crt'
|
8
|
-
req = simple_http_request(
|
8
|
+
req = simple_http_request(uri.host, uri.path)
|
9
9
|
|
10
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
10
11
|
process_certificate_status = lambda do |res, cert, chain|
|
11
12
|
puts 'stapled OCSPResponse: '
|
12
13
|
puts res.basic.status.pretty_inspect unless res.nil?
|
@@ -14,15 +15,13 @@ process_certificate_status = lambda do |res, cert, chain|
|
|
14
15
|
|
15
16
|
TTTLS13::Client.softfail_check_certificate_status(res, cert, chain)
|
16
17
|
end
|
17
|
-
|
18
|
-
socket = TCPSocket.new(hostname, port)
|
19
18
|
settings = {
|
20
19
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
21
20
|
alpn: ['http/1.1'],
|
22
21
|
check_certificate_status: true,
|
23
22
|
process_certificate_status: process_certificate_status
|
24
23
|
}
|
25
|
-
client = TTTLS13::Client.new(socket,
|
24
|
+
client = TTTLS13::Client.new(socket, uri.host, **settings)
|
26
25
|
client.connect
|
27
26
|
client.write(req)
|
28
27
|
|
@@ -3,9 +3,9 @@
|
|
3
3
|
|
4
4
|
require_relative 'helper'
|
5
5
|
|
6
|
-
|
6
|
+
uri = URI.parse(ARGV[0] || 'https://localhost:4433')
|
7
7
|
ca_file = __dir__ + '/../tmp/ca.crt'
|
8
|
-
req = simple_http_request(
|
8
|
+
req = simple_http_request(uri.host, uri.path)
|
9
9
|
|
10
10
|
settings_2nd = {
|
11
11
|
ca_file: File.exist?(ca_file) ? ca_file : nil,
|
@@ -33,10 +33,11 @@ settings_1st = {
|
|
33
33
|
# Subsequent Handshake:
|
34
34
|
settings_2nd
|
35
35
|
].each do |settings|
|
36
|
-
socket = TCPSocket.new(
|
37
|
-
client = TTTLS13::Client.new(socket,
|
36
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
37
|
+
client = TTTLS13::Client.new(socket, uri.host, **settings)
|
38
38
|
client.connect
|
39
39
|
client.write(req)
|
40
|
+
|
40
41
|
print recv_http_response(client)
|
41
42
|
client.close unless client.eof?
|
42
43
|
socket.close
|
data/example/https_server.rb
CHANGED
@@ -30,7 +30,20 @@ Etc.nprocessors.times do
|
|
30
30
|
parser.on_message_complete = lambda do
|
31
31
|
if !parser.http_method.nil?
|
32
32
|
logger.info 'Receive Request'
|
33
|
-
|
33
|
+
html = <<HTML
|
34
|
+
<!DOCTYPE html>
|
35
|
+
<html>
|
36
|
+
<head>
|
37
|
+
<meta charset="UTF-8" />
|
38
|
+
<title>tttls1.3 test server</title>
|
39
|
+
</head>
|
40
|
+
<body>
|
41
|
+
%s
|
42
|
+
</body>
|
43
|
+
</html>
|
44
|
+
HTML
|
45
|
+
html = format(html, transcript_htmlize(server.transcript))
|
46
|
+
server.write(simple_http_response(html))
|
34
47
|
server.close
|
35
48
|
else
|
36
49
|
logger.warn 'Not Request'
|