From 5da14042f70711ea5cf66e034699730335462f66 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 5 May 2024 14:08:03 +0200 Subject: Merging upstream version 1.45.3+dfsg. Signed-off-by: Daniel Baumann --- .../libh2o/examples/doc_root.alternate/index.txt | 1 + .../server/h2o/libh2o/examples/doc_root/index.html | 10 + .../server/h2o/libh2o/examples/h2o/alternate.crt | 20 ++ .../server/h2o/libh2o/examples/h2o/alternate.key | 27 ++ src/web/server/h2o/libh2o/examples/h2o/h2o.conf | 24 ++ src/web/server/h2o/libh2o/examples/h2o/server.crt | 20 ++ src/web/server/h2o/libh2o/examples/h2o/server.key | 27 ++ .../server/h2o/libh2o/examples/h2o_mruby/h2o.conf | 25 ++ .../server/h2o/libh2o/examples/h2o_mruby/hello.rb | 32 ++ .../h2o/libh2o/examples/libh2o/http1client.c | 179 ++++++++++ .../libh2o/examples/libh2o/latency-optimization.c | 381 +++++++++++++++++++++ src/web/server/h2o/libh2o/examples/libh2o/simple.c | 264 ++++++++++++++ .../h2o/libh2o/examples/libh2o/socket-client.c | 163 +++++++++ .../server/h2o/libh2o/examples/libh2o/websocket.c | 143 ++++++++ 14 files changed, 1316 insertions(+) create mode 100644 src/web/server/h2o/libh2o/examples/doc_root.alternate/index.txt create mode 100644 src/web/server/h2o/libh2o/examples/doc_root/index.html create mode 100644 src/web/server/h2o/libh2o/examples/h2o/alternate.crt create mode 100644 src/web/server/h2o/libh2o/examples/h2o/alternate.key create mode 100644 src/web/server/h2o/libh2o/examples/h2o/h2o.conf create mode 100644 src/web/server/h2o/libh2o/examples/h2o/server.crt create mode 100644 src/web/server/h2o/libh2o/examples/h2o/server.key create mode 100644 src/web/server/h2o/libh2o/examples/h2o_mruby/h2o.conf create mode 100644 src/web/server/h2o/libh2o/examples/h2o_mruby/hello.rb create mode 100644 src/web/server/h2o/libh2o/examples/libh2o/http1client.c create mode 100644 src/web/server/h2o/libh2o/examples/libh2o/latency-optimization.c create mode 100644 src/web/server/h2o/libh2o/examples/libh2o/simple.c create mode 100644 src/web/server/h2o/libh2o/examples/libh2o/socket-client.c create mode 100644 src/web/server/h2o/libh2o/examples/libh2o/websocket.c (limited to 'src/web/server/h2o/libh2o/examples') diff --git a/src/web/server/h2o/libh2o/examples/doc_root.alternate/index.txt b/src/web/server/h2o/libh2o/examples/doc_root.alternate/index.txt new file mode 100644 index 000000000..ce0136250 --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/doc_root.alternate/index.txt @@ -0,0 +1 @@ +hello diff --git a/src/web/server/h2o/libh2o/examples/doc_root/index.html b/src/web/server/h2o/libh2o/examples/doc_root/index.html new file mode 100644 index 000000000..2d8ed62ff --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/doc_root/index.html @@ -0,0 +1,10 @@ + + + + Welcome to H2O + + +

Welcome to H2O - an optimized HTTP server

+

It works!

+ + diff --git a/src/web/server/h2o/libh2o/examples/h2o/alternate.crt b/src/web/server/h2o/libh2o/examples/h2o/alternate.crt new file mode 100644 index 000000000..3aeabcc93 --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/h2o/alternate.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDRDCCAiygAwIBAgIBAjANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDEwtIMk8g +VGVzdCBDQTAeFw0xNDEyMTAyMDExMDJaFw0yNDEyMDcyMDExMDJaMCUxIzAhBgNV +BAMTGmFsdGVybmF0ZS4xMjcuMC4wLjEueGlwLmlvMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAvCryCZFMzkqYRH9v9i8hmJiEzH7QZpFJkWYnmqUUAeJM +wqwZGW0U27aKschexdBesLsjCpRwKgT+8yKncc+cfwVCnWdkbW/gfsdHr9/YggNp +Vh/g8LKyhPOdc325y0CHMaoSet+BM3NXEA67b512cF7STqKM4wG5Jtn61Bj0aWF6 +7D1zGb7vY1xWb8GpgIywIQcg22t5NHMZ2vR6FFiYarax9X2DfL69gkdhmg8Kzg6z +ZdmfPl7t0UDC5nRnnZkpFzMuermxnjcduEMAY+/Hz0D+dGVGxbiipNizjO8p7109 +T7y4rUVPB0i9cSbnP573VPgwHps7KhgaiTcxQrAlAQIDAQABo4GNMIGKMAkGA1Ud +EwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmlj +YXRlMB0GA1UdDgQWBBQN19Rc5yx1CxcKN+hvlUXtC3Vl/jAwBgNVHSMEKTAnoRqk +GDAWMRQwEgYDVQQDEwtIMk8gVGVzdCBDQYIJAJqktVew7822MA0GCSqGSIb3DQEB +CwUAA4IBAQCXgCil1Y17EOMJLN8dHWwaNVYkMq6YGMJRdX2Uxn5Sklv2mGHIVpgH +UV2u2jBcgYaHMHFBvBPsQ/mjOdvGY3S+ci+MWwp1yXa3YvQus1C0ZZpAmq+vtI0F +bfWi+uAEkU5B+9M6LYX3IWPUo1UrbexP0UPpxnIfphH+c746zvomX2hSaKlYL+oa +9lqaBvLYEZvxM5UShLkRvD59MoXSG1TUJdwG6Pu0aasN9xiJ2lJhSxrDf/jGOEqV +PckG3y+eNc9EVnt5FULoQisGxC5N6AHsDebX8/Hkbh6POXU8nLQZzeTBWyMVWmSI +ckH5BgMtJ5UCt6q4WH0gFV7DNqIShx86 +-----END CERTIFICATE----- diff --git a/src/web/server/h2o/libh2o/examples/h2o/alternate.key b/src/web/server/h2o/libh2o/examples/h2o/alternate.key new file mode 100644 index 000000000..3a144e9b5 --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/h2o/alternate.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAvCryCZFMzkqYRH9v9i8hmJiEzH7QZpFJkWYnmqUUAeJMwqwZ +GW0U27aKschexdBesLsjCpRwKgT+8yKncc+cfwVCnWdkbW/gfsdHr9/YggNpVh/g +8LKyhPOdc325y0CHMaoSet+BM3NXEA67b512cF7STqKM4wG5Jtn61Bj0aWF67D1z +Gb7vY1xWb8GpgIywIQcg22t5NHMZ2vR6FFiYarax9X2DfL69gkdhmg8Kzg6zZdmf +Pl7t0UDC5nRnnZkpFzMuermxnjcduEMAY+/Hz0D+dGVGxbiipNizjO8p7109T7y4 +rUVPB0i9cSbnP573VPgwHps7KhgaiTcxQrAlAQIDAQABAoIBAQC49qoGt5o9Kdw1 +cON4pmmq2zmm3n0yZVxgnX8Op3hcRbvYnFzrvmsDcpMxINnwLtv1c26FhtYep9yI +2SapXD/kKCKMIUb5wEB3vqH8AtiLLJlNvHZbg/yxbdr23L5WSe7a5efWen9BOP56 +3VBn7euvl7W48FX3CwmaZCkIdiNCtYqY4IYrca52Z0GPO9Ah2E9JGRj1LNV0KW1w +dc5UaM+BXVqJ5EclIPm+MndqaXOBl8/HndUx/W9rFfvvVnltIqad7Mlh45OufIGj +1KqVK8NzEiUeIJrqowNjNnLxifEFoilk9+v6TV1ib90mSuyfMVzyyDwXK1MaNuMW +9BZDOeMlAoGBAPSzKNUBQjh8oCn99ti/QTZjWQ3oLuDnZkbkLKB3XZiF/tIy5aDF +C2LDTwr6evcTcraS/8bsouAxrBLoSDZNYlv7wbgKJt4rpxe0KYkwecMA+u+eCL9C +YaRThBfp/Gu2gIFU2vI3nktnyIe8RRFA3G3atZZjszP2minf3Ff2DF7rAoGBAMTb +dsB4O+KiH56dkh5zCClteFbauAQ7I/AIgMtXm7XzfVn2mZUSGv1Alq2nw931XpkR +8w5QFDYvuyBkZwreJ/Kpb4CYICJXHUknLO6Sisutn0AfwXkgcE2HGfgUmNok5pv2 +TH9WqbKf6cHUBWLrb2Ip4lebgdrrFJBlOvUuxYjDAoGANipucHAd43kazxDLkoEL +g2mMbfqmXdx7FFgv1Ll3e2q11Hu1vte/RHZtScXWcFjavLVfbv40s6HrMChAy9xn +WGsrH30Hy4goLaQQybB0U4klAuOdlhCwonpmNBD0cjdszLQm3xUWsiRgDEPNmhsc +cCjIp2icY3VD/N7z3Hi3lk8CgYBnL2IfoOZC9Rf93DorG8C7dlYNsLekABvmRY69 +Bz7nMKoT7d6y9LqQ5LoWbEmOnn7nXTE531+4x2wenoIkgC4QVB/OF+9AEMmY/p/e +rZFzEZ7Xzc1r4ET9XkOOdb1pGs6GEaQnWxW4O3obzzbDkwTfP3UU1r5KMc6loWo1 ++j4wYQKBgQDsnzQsrWHXxsZHlgpvtjn1RyYHHCdbtavrZ/g718cwOR4lqf8fz+is +dP49yhLhDu2dKUsTNm76LVjKvnNhoaq9nuiQtl77ANO7YEjl0SJw79src5+tu7qr +gp/zY45QbQzYcLa7RdIkQEqvcSfME+rBeIrjKPVH+MM2XjDQJ8IekA== +-----END RSA PRIVATE KEY----- diff --git a/src/web/server/h2o/libh2o/examples/h2o/h2o.conf b/src/web/server/h2o/libh2o/examples/h2o/h2o.conf new file mode 100644 index 000000000..52749c518 --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/h2o/h2o.conf @@ -0,0 +1,24 @@ +# to find out the configuration commands, run: h2o --help + +listen: 8080 +listen: + port: 8081 + ssl: + certificate-file: examples/h2o/server.crt + key-file: examples/h2o/server.key +hosts: + "127.0.0.1.xip.io:8080": + paths: + /: + file.dir: examples/doc_root + access-log: /dev/stdout + "alternate.127.0.0.1.xip.io:8081": + listen: + port: 8081 + ssl: + certificate-file: examples/h2o/alternate.crt + key-file: examples/h2o/alternate.key + paths: + /: + file.dir: examples/doc_root.alternate + access-log: /dev/stdout diff --git a/src/web/server/h2o/libh2o/examples/h2o/server.crt b/src/web/server/h2o/libh2o/examples/h2o/server.crt new file mode 100644 index 000000000..07438a975 --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/h2o/server.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDOjCCAiKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDEwtIMk8g +VGVzdCBDQTAeFw0xNDEyMTAxOTMzMDVaFw0yNDEyMDcxOTMzMDVaMBsxGTAXBgNV +BAMTEDEyNy4wLjAuMS54aXAuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDvNmF5nimH3wlp50E2/2SqxUD0JKaF3r2QFz1kB9UUwDhVDCms6PdkavF/ +bQcHcWS+oa97D1miBQXo2Ns+6Z6JQ5sak/bVjnBxiU8vhqiOWvAwH947E4Km5HJB +NFJJ7WEM+90kAFB2ayEM/llIQEt1RKCs2fgpaEgOMWPUAdcgyp6pNd60W5GA3Md2 +1tdDH5RYGKzYHqpkm6pICtvaaxU4LwPmA3Oc8+VDDsVt08Jos1dJvoacjQTS6PpC +ZiUDD2zqeSA//PGN8WV2o81SmsZwSpPCYBvxVW13tdsA1ivO5tng2fr9ZesKtXFZ +SaH/tKmB3Br8jg2vUke/0cfIvbP/AgMBAAGjgY0wgYowCQYDVR0TBAIwADAsBglg +hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O +BBYEFJXhddVQ68vtPvxoHWHsYkLnu3+4MDAGA1UdIwQpMCehGqQYMBYxFDASBgNV +BAMTC0gyTyBUZXN0IENBggkAmqS1V7DvzbYwDQYJKoZIhvcNAQELBQADggEBAJQ2 +uvzL/lZnrsF4cvHhl/mg+s/RjHwvqFRrxOWUeWu2BQOGdd1Izqr8ZbF35pevPkXe +j3zQL4Nf8OxO/gx4w0165KL4dYxEW7EaxsDQUI2aXSW0JNSvK2UGugG4+E4aT+9y +cuBCtfWbL4/N6IMt2QW17B3DcigkreMoZavnnqRecQWkOx4nu0SmYg1g2QV4kRqT +nvLt29daSWjNhP3dkmLTxn19umx26/JH6rqcgokDfHHO8tlDbc9JfyxYH01ZP2Ps +esIiGa/LBXfKiPXxyHuNVQI+2cMmIWYf+Eu/1uNV3K55fA8806/FeklcQe/vvSCU +Vw6RN5S/14SQnMYWr7E= +-----END CERTIFICATE----- diff --git a/src/web/server/h2o/libh2o/examples/h2o/server.key b/src/web/server/h2o/libh2o/examples/h2o/server.key new file mode 100644 index 000000000..85a6f25f6 --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/h2o/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA7zZheZ4ph98JaedBNv9kqsVA9CSmhd69kBc9ZAfVFMA4VQwp +rOj3ZGrxf20HB3FkvqGvew9ZogUF6NjbPumeiUObGpP21Y5wcYlPL4aojlrwMB/e +OxOCpuRyQTRSSe1hDPvdJABQdmshDP5ZSEBLdUSgrNn4KWhIDjFj1AHXIMqeqTXe +tFuRgNzHdtbXQx+UWBis2B6qZJuqSArb2msVOC8D5gNznPPlQw7FbdPCaLNXSb6G +nI0E0uj6QmYlAw9s6nkgP/zxjfFldqPNUprGcEqTwmAb8VVtd7XbANYrzubZ4Nn6 +/WXrCrVxWUmh/7Spgdwa/I4Nr1JHv9HHyL2z/wIDAQABAoIBAEVPf2zKrAPnVwXt +cJLr6xIj908GM43EXS6b3TjXoCDUFT5nOMgV9GCPMAwY3hmE/IjTtlG0v+bXB8BQ +3S3caQgio5VO3A1CqUfsXhpKLRqaNM/s2+pIG+oZdRV5gIJVGnK1o3yj7qxxG/F0 +3Q+3OWXwDZIn0eTFh2M9YkxygA/KtkREZWv8Q8qZpdOpJSBYZyGE97Jqy/yGc+DQ +Vpoa9B8WwnIdUn47TkZfsbzqGIYZxatJQDC1j7Y+F8So7zBbUhpz7YqATQwf5Efm +K2xwvlwfdwykq6ffEr2M/Xna0220G2JZlGq3Cs2X9GT9Pt9OS86Bz+EL46ELo0tZ +yfHQe/kCgYEA+zh4k2be6fhQG+ChiG3Ue5K/kH2prqyGBus61wHnt8XZavqBevEy +4pdmvJ6Q1Ta9Z2YCIqqNmlTdjZ6B35lvAK8YFITGy0MVV6K5NFYVfhALWCQC2r3B +6uH39FQ0mDo3gS5ZjYlUzbu67LGFnyX+pyMr2oxlhI1fCY3VchXQAOsCgYEA88Nt +CwSOaZ1fWmyNAgXEAX1Jx4XLFYgjcA/YBXW9gfQ0AfufB346y53PsgjX1lB+Bbcg +cY/o5W7F0b3A0R4K5LShlPCq8iB2DC+VnpKwTgo8ylh+VZCPy2BmMK0jrrmyqWeg +PzwgP0lp+7l/qW8LDImeYi8nWoqd6f1ye4iJdD0CgYEAlIApJljk5EFYeWIrmk3y +EKoKewsNRqfNAkICoh4KL2PQxaAW8emqPq9ol47T5nVZOMnf8UYINnZ8EL7l3psA +NtNJ1Lc4G+cnsooKGJnaUo6BZjTDSzJocsPoopE0Fdgz/zS60yOe8Y5LTKcTaaQ4 +B+yOe74KNHSs/STOS4YBUskCgYAIqaRBZPsOo8oUs5DbRostpl8t2QJblIf13opF +v2ZprN0ASQngwUqjm8sav5e0BQ5Fc7mSb5POO36KMp0ckV2/vO+VFGxuyFqJmlNN +3Fapn1GDu1tZ/RYvGxDmn/CJsA26WXVnaeKXfStoB7KSueCBpI5dXOGgJRbxjtE3 +tKV13QKBgQCtmLtTJPJ0Z+9n85C8kBonk2MCnD9JTYWoDQzNMYGabthzSqJqcEek +dvhr82XkcHM+r6+cirjdQr4Qj7/2bfZesHl5XLvoJDB1YJIXnNJOELwbktrJrXLc +dJ+MMvPvBAMah/tqr2DqgTGfWLDt9PJiCJVsuN2kD9toWHV08pY0Og== +-----END RSA PRIVATE KEY----- diff --git a/src/web/server/h2o/libh2o/examples/h2o_mruby/h2o.conf b/src/web/server/h2o/libh2o/examples/h2o_mruby/h2o.conf new file mode 100644 index 000000000..cf94ec3ab --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/h2o_mruby/h2o.conf @@ -0,0 +1,25 @@ +# to find out the configuration commands, run: h2o --help + +listen: 8080 +listen: + port: 8081 + ssl: + certificate-file: examples/h2o/server.crt + key-file: examples/h2o/server.key +hosts: + "127.0.0.1.xip.io:8080": + paths: + /: + file.dir: examples/doc_root + mruby.handler-file: examples/h2o_mruby/hello.rb + access-log: /dev/stdout + "alternate.127.0.0.1.xip.io:8081": + listen: + port: 8081 + ssl: + certificate-file: examples/h2o/alternate.crt + key-file: examples/h2o/alternate.key + paths: + /: + file.dir: examples/doc_root.alternate + access-log: /dev/stdout diff --git a/src/web/server/h2o/libh2o/examples/h2o_mruby/hello.rb b/src/web/server/h2o/libh2o/examples/h2o_mruby/hello.rb new file mode 100644 index 000000000..bceb7b0cd --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/h2o_mruby/hello.rb @@ -0,0 +1,32 @@ +# paths: +# /: +# file.dir: examples/doc_root +# mruby.handler-file: /path/to/hello.rb + +class HelloApp + def call(env) + h = "hello" + m = "from h2o_mruby" + + ua = env["HTTP_USER_AGENT"] + new_ua = "new-#{ua}-h2o_mruby" + path = env["PATH_INFO"] + host = env["HTTP_HOST"] + method = env["REQUEST_METHOD"] + query = env["QUERY_STRING"] + input = env["rack.input"] ? env["rack.input"].read : "" + + msg = "#{h} #{m}. User-Agent:#{ua} New User-Agent:#{new_ua} path:#{path} host:#{host} method:#{method} query:#{query} input:#{input}" + + [200, + { + "content-type" => "text/plain; charset=utf-8", + "user-agent" => new_ua, + }, + ["#{msg}\n"] + ] + + end +end + +HelloApp.new diff --git a/src/web/server/h2o/libh2o/examples/libh2o/http1client.c b/src/web/server/h2o/libh2o/examples/libh2o/http1client.c new file mode 100644 index 000000000..bcf9b94b2 --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/libh2o/http1client.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2014 DeNA Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include +#include +#include "h2o.h" + +static h2o_socketpool_t *sockpool; +static h2o_mem_pool_t pool; +static const char *url; +static int cnt_left = 3; + +static h2o_http1client_head_cb on_connect(h2o_http1client_t *client, const char *errstr, h2o_iovec_t **reqbufs, size_t *reqbufcnt, + int *method_is_head); +static h2o_http1client_body_cb on_head(h2o_http1client_t *client, const char *errstr, int minor_version, int status, + h2o_iovec_t msg, h2o_header_t *headers, size_t num_headers); + +static void start_request(h2o_http1client_ctx_t *ctx) +{ + h2o_url_t url_parsed; + h2o_iovec_t *req; + int is_ssl; + + /* clear memory pool */ + h2o_mem_clear_pool(&pool); + + /* parse URL */ + if (h2o_url_parse(url, SIZE_MAX, &url_parsed) != 0) { + fprintf(stderr, "unrecognized type of URL: %s\n", url); + exit(1); + } + is_ssl = url_parsed.scheme == &H2O_URL_SCHEME_HTTPS; + + /* build request */ + req = h2o_mem_alloc_pool(&pool, sizeof(*req)); + req->base = h2o_mem_alloc_pool(&pool, 1024); + req->len = snprintf(req->base, 1024, "GET %.*s HTTP/1.1\r\nhost: %.*s\r\n\r\n", (int)url_parsed.path.len, url_parsed.path.base, + (int)url_parsed.authority.len, url_parsed.authority.base); + assert(req->len < 1024); + + /* initiate the request */ + if (1) { + if (sockpool == NULL) { + sockpool = h2o_mem_alloc(sizeof(*sockpool)); + h2o_socketpool_init_by_hostport(sockpool, url_parsed.host, h2o_url_get_port(&url_parsed), is_ssl, 10); + h2o_socketpool_set_timeout(sockpool, ctx->loop, 5000 /* in msec */); + } + h2o_http1client_connect_with_pool(NULL, req, ctx, sockpool, on_connect); + } else { + h2o_http1client_connect(NULL, req, ctx, url_parsed.host, h2o_url_get_port(&url_parsed), is_ssl, on_connect); + } +} + +static int on_body(h2o_http1client_t *client, const char *errstr) +{ + if (errstr != NULL && errstr != h2o_http1client_error_is_eos) { + fprintf(stderr, "%s\n", errstr); + exit(1); + return -1; + } + + fwrite(client->sock->input->bytes, 1, client->sock->input->size, stdout); + h2o_buffer_consume(&client->sock->input, client->sock->input->size); + + if (errstr == h2o_http1client_error_is_eos) { + if (--cnt_left != 0) { + /* next attempt */ + h2o_mem_clear_pool(&pool); + start_request(client->ctx); + } + } + + return 0; +} + +h2o_http1client_body_cb on_head(h2o_http1client_t *client, const char *errstr, int minor_version, int status, h2o_iovec_t msg, + h2o_header_t *headers, size_t num_headers) +{ + size_t i; + + if (errstr != NULL && errstr != h2o_http1client_error_is_eos) { + fprintf(stderr, "%s\n", errstr); + exit(1); + return NULL; + } + + printf("HTTP/1.%d %d %.*s\n", minor_version, status, (int)msg.len, msg.base); + for (i = 0; i != num_headers; ++i) + printf("%.*s: %.*s\n", (int)headers[i].name->len, headers[i].name->base, (int)headers[i].value.len, headers[i].value.base); + printf("\n"); + + if (errstr == h2o_http1client_error_is_eos) { + fprintf(stderr, "no body\n"); + exit(1); + return NULL; + } + + return on_body; +} + +h2o_http1client_head_cb on_connect(h2o_http1client_t *client, const char *errstr, h2o_iovec_t **reqbufs, size_t *reqbufcnt, + int *method_is_head) +{ + if (errstr != NULL) { + fprintf(stderr, "%s\n", errstr); + exit(1); + return NULL; + } + + *reqbufs = (h2o_iovec_t *)client->data; + *reqbufcnt = 1; + *method_is_head = 0; + + return on_head; +} + +int main(int argc, char **argv) +{ + h2o_multithread_queue_t *queue; + h2o_multithread_receiver_t getaddr_receiver; + h2o_timeout_t io_timeout; + h2o_http1client_ctx_t ctx = {NULL, &getaddr_receiver, &io_timeout}; + + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + ctx.ssl_ctx = SSL_CTX_new(TLSv1_client_method()); + SSL_CTX_load_verify_locations(ctx.ssl_ctx, H2O_TO_STR(H2O_ROOT) "/share/h2o/ca-bundle.crt", NULL); + SSL_CTX_set_verify(ctx.ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + url = argv[1]; + + h2o_mem_init_pool(&pool); + +/* setup context */ +#if H2O_USE_LIBUV + ctx.loop = uv_loop_new(); +#else + ctx.loop = h2o_evloop_create(); +#endif + queue = h2o_multithread_create_queue(ctx.loop); + h2o_multithread_register_receiver(queue, ctx.getaddr_receiver, h2o_hostinfo_getaddr_receiver); + h2o_timeout_init(ctx.loop, &io_timeout, 5000); /* 5 seconds */ + + /* setup the first request */ + start_request(&ctx); + + while (cnt_left != 0) { +#if H2O_USE_LIBUV + uv_run(ctx.loop, UV_RUN_ONCE); +#else + h2o_evloop_run(ctx.loop, INT32_MAX); +#endif + } + + return 0; +} diff --git a/src/web/server/h2o/libh2o/examples/libh2o/latency-optimization.c b/src/web/server/h2o/libh2o/examples/libh2o/latency-optimization.c new file mode 100644 index 000000000..de34bc9c6 --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/libh2o/latency-optimization.c @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2014 DeNA Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "h2o/socket.h" +#include "h2o/string_.h" + +/* configuration */ +static char *host, *port; +static SSL_CTX *ssl_ctx; +static int mode_server, server_flag_received; +static h2o_socket_latency_optimization_conditions_t latopt_cond = {.min_rtt = 50, .max_additional_delay = 10, .max_cwnd = 65535}; +size_t write_block_size = 65536; + +/* globals */ +static h2o_loop_t *loop; +static h2o_socket_t *sock; +static struct { + uint64_t resp_start_at; + uint64_t sig_received_at; + uint64_t bytes_received; + uint64_t bytes_before_sig; +} client_stats; + +static void server_write(h2o_socket_t *sock); + +static h2o_iovec_t prepare_write_buf(void) +{ + static h2o_iovec_t buf; + if (buf.base == NULL) { + buf.base = h2o_mem_alloc(write_block_size); + buf.len = write_block_size; + memset(buf.base, '0', buf.len); + } + return buf; +} + +static void server_on_write_ready(h2o_socket_t *sock, const char *err) +{ + if (err != NULL) { + fprintf(stderr, "socket unexpected closed by peer:%s\n", err); + exit(1); + return; + } + server_write(sock); +} + +static void server_on_write_complete(h2o_socket_t *sock, const char *err) +{ + if (err != NULL) { + fprintf(stderr, "write failed:%s\n", err); + exit(1); + return; + } + h2o_socket_notify_write(sock, server_on_write_ready); +} + +void server_write(h2o_socket_t *sock) +{ + size_t sz = h2o_socket_prepare_for_latency_optimized_write(sock, &latopt_cond); + h2o_iovec_t buf = prepare_write_buf(); + + if (server_flag_received) + buf.base[0] = '1'; + if (sz < buf.len) + buf.len = sz; + + fprintf(stderr, "writing %zu bytes\n", buf.len); + h2o_socket_write(sock, &buf, 1, server_on_write_complete); +} + +static void server_on_read_second(h2o_socket_t *sock, const char *err) +{ + if (err != NULL) { + fprintf(stderr, "connection closed unexpectedly:%s\n", err); + exit(1); + return; + } + + fprintf(stderr, "received the flag\n"); + server_flag_received = 1; +} + +static void server_on_read_first(h2o_socket_t *sock, const char *err) +{ + if (err != NULL) { + fprintf(stderr, "connection closed unexpectedly:%s\n", err); + exit(1); + return; + } + + server_write(sock); + h2o_socket_read_start(sock, server_on_read_second); +} + +static void client_on_write_complete(h2o_socket_t *sock, const char *err) +{ + if (err == NULL) + return; + /* handle error */ + fprintf(stderr, "write failed:%s\n", err); + h2o_socket_close(sock); + exit(1); +} + +static void client_on_read_second(h2o_socket_t *sock, const char *err) +{ + size_t i; + + if (err != NULL) { + fprintf(stderr, "connection closed unexpectedly:%s\n", err); + exit(1); + return; + } + + if (client_stats.sig_received_at == 0) { + for (i = 0; i != sock->input->size; ++i) { + if (sock->input->bytes[i] != '0') { + client_stats.sig_received_at = h2o_now(h2o_socket_get_loop(sock)); + break; + } + ++client_stats.bytes_before_sig; + } + } + client_stats.bytes_received += sock->input->size; + h2o_buffer_consume(&sock->input, sock->input->size); + + if (client_stats.bytes_received >= 1024 * 1024) { + uint64_t now = h2o_now(h2o_socket_get_loop(sock)); + printf("Delay: %" PRIu64 " octets, %" PRIu64 " ms\n", client_stats.bytes_before_sig, + client_stats.sig_received_at - client_stats.resp_start_at); + printf("Total: %" PRIu64 " octets, %" PRIu64 " ms\n", client_stats.bytes_received, now - client_stats.resp_start_at); + exit(0); + } +} + +static void client_on_read_first(h2o_socket_t *sock, const char *err) +{ + if (err != NULL) { + fprintf(stderr, "connection closed unexpectedly:%s\n", err); + exit(1); + return; + } + + client_stats.resp_start_at = h2o_now(h2o_socket_get_loop(sock)); + client_stats.bytes_before_sig = sock->input->size; + client_stats.bytes_received = sock->input->size; + h2o_buffer_consume(&sock->input, sock->input->size); + + h2o_iovec_t data = {H2O_STRLIT("!")}; + h2o_socket_write(sock, &data, 1, client_on_write_complete); + h2o_socket_read_start(sock, client_on_read_second); +} + +static void on_handshake_complete(h2o_socket_t *sock, const char *err) +{ + if (err != NULL && err != h2o_socket_error_ssl_cert_name_mismatch) { + /* TLS handshake failed */ + fprintf(stderr, "TLS handshake failure:%s\n", err); + ERR_print_errors_fp(stderr); + h2o_socket_close(sock); + exit(1); + return; + } + + if (mode_server) { + h2o_socket_read_start(sock, server_on_read_first); + } else { + h2o_iovec_t buf = {H2O_STRLIT("0")}; + h2o_socket_write(sock, &buf, 1, client_on_write_complete); + h2o_socket_read_start(sock, client_on_read_first); + } +} + +static void on_connect(h2o_socket_t *sock, const char *err) +{ + if (err != NULL) { + /* connection failed */ + fprintf(stderr, "failed to connect to host:%s\n", err); + h2o_socket_close(sock); + exit(1); + return; + } + + if (ssl_ctx != NULL) { + h2o_socket_ssl_handshake(sock, ssl_ctx, mode_server ? NULL : "blahblah", on_handshake_complete); + } else { + on_handshake_complete(sock, NULL); + } +} + +static void on_accept(h2o_socket_t *listener, const char *err) +{ + if (err != NULL) + return; + + if ((sock = h2o_evloop_socket_accept(listener)) != NULL) { + h2o_socket_close(listener); + if (ssl_ctx != NULL) { + h2o_socket_ssl_handshake(sock, ssl_ctx, mode_server ? NULL : "blahblah", on_handshake_complete); + } else { + on_handshake_complete(sock, NULL); + } + } +} + +static void usage(const char *cmd) +{ + fprintf(stderr, "Usage: %s [opts] [:]\n" + "Options: --listen if set, waits for incoming connection. Otherwise,\n" + " connects to the server running at given address\n" + " --reverse-role if set, reverses the role bet. server and the\n" + " client once the connection is established\n" + " --tls use TLS\n" + " --block-size=octets default write block size\n" + " --min-rtt=ms minimum RTT to enable latency optimization\n" + " --max-cwnd=octets maximum size of CWND to enable latency\n" + " optimization\n", + cmd); + exit(1); +} + +int main(int argc, char **argv) +{ + static const struct option longopts[] = {{"listen", no_argument, NULL, 'l'}, + {"reverse-role", no_argument, NULL, 'r'}, + {"tls", no_argument, NULL, 't'}, + {"block-size", no_argument, NULL, 'b'}, + {"min-rtt", required_argument, NULL, 'R'}, + {"max-cwnd", required_argument, NULL, 'c'}, + {}}; + int opt_ch, mode_listen = 0, mode_reverse_role = 0, mode_tls = 0; + struct addrinfo hints, *res = NULL; + int err; + + while ((opt_ch = getopt_long(argc, argv, "lrtb:R:c:", longopts, NULL)) != -1) { + switch (opt_ch) { + case 'l': + mode_listen = 1; + break; + case 'r': + mode_reverse_role = 1; + break; + case 't': + mode_tls = 1; + break; + case 'b': + if (sscanf(optarg, "%zu", &write_block_size) != 1) { + fprintf(stderr, "write block size (-b) must be a non-negative number of octets\n"); + exit(1); + } + break; + case 'R': + if (sscanf(optarg, "%u", &latopt_cond.min_rtt) != 1) { + fprintf(stderr, "min RTT (-m) must be a non-negative number in milliseconds\n"); + exit(1); + } + break; + case 'c': + if (sscanf(optarg, "%u", &latopt_cond.max_cwnd) != 1) { + fprintf(stderr, "max CWND size must be a non-negative number of octets\n"); + exit(1); + } + break; + default: + usage(argv[0]); + break; + } + } + mode_server = mode_listen; + if (mode_reverse_role) + mode_server = !mode_server; + + if (argc == optind) { + usage(argv[0]); + } else { + char *hostport = argv[optind], *colon; + if ((colon = strchr(hostport, ':')) != NULL) { + hostport = argv[optind]; + host = strdup(hostport); + host[colon - hostport] = '\0'; + port = colon + 1; + } else { + host = "0.0.0.0"; + port = argv[optind]; + } + } + + if (mode_tls) { + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + if (mode_server) { + ssl_ctx = SSL_CTX_new(SSLv23_server_method()); + SSL_CTX_use_certificate_file(ssl_ctx, "examples/h2o/server.crt", SSL_FILETYPE_PEM); + SSL_CTX_use_PrivateKey_file(ssl_ctx, "examples/h2o/server.key", SSL_FILETYPE_PEM); + } else { + ssl_ctx = SSL_CTX_new(SSLv23_client_method()); + } + int nid = NID_X9_62_prime256v1; + EC_KEY *key = EC_KEY_new_by_curve_name(nid); + if (key == NULL) { + fprintf(stderr, "Failed to create curve \"%s\"\n", OBJ_nid2sn(nid)); + exit(1); + } + SSL_CTX_set_tmp_ecdh(ssl_ctx, key); + EC_KEY_free(key); + SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + SSL_CTX_set_cipher_list(ssl_ctx, "ECDHE-RSA-AES128-GCM-SHA256"); + } + +#if H2O_USE_LIBUV + loop = uv_loop_new(); +#else + loop = h2o_evloop_create(); +#endif + + /* resolve host:port (FIXME use the function supplied by the loop) */ + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_ADDRCONFIG; + if ((err = getaddrinfo(host, port, &hints, &res)) != 0) { + fprintf(stderr, "failed to resolve %s:%s:%s\n", host, port, gai_strerror(err)); + exit(1); + } + + if (mode_listen) { + int fd, reuseaddr_flag = 1; + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 || + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_flag, sizeof(reuseaddr_flag)) != 0 || + bind(fd, res->ai_addr, res->ai_addrlen) != 0 || listen(fd, SOMAXCONN) != 0) { + fprintf(stderr, "failed to listen to %s:%s:%s\n", host, port, strerror(errno)); + exit(1); + } + h2o_socket_t *listen_sock = h2o_evloop_socket_create(loop, fd, H2O_SOCKET_FLAG_DONT_READ); + h2o_socket_read_start(listen_sock, on_accept); + } else { + if ((sock = h2o_socket_connect(loop, res->ai_addr, res->ai_addrlen, on_connect)) == NULL) { + fprintf(stderr, "failed to create socket:%s\n", strerror(errno)); + exit(1); + } + } + + while (1) { +#if H2O_USE_LIBUV + uv_run(loop, UV_RUN_DEFAULT); +#else + h2o_evloop_run(loop, INT32_MAX); +#endif + } + + return 0; +} diff --git a/src/web/server/h2o/libh2o/examples/libh2o/simple.c b/src/web/server/h2o/libh2o/examples/libh2o/simple.c new file mode 100644 index 000000000..bb72bf60c --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/libh2o/simple.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2014 DeNA Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "h2o.h" +#include "h2o/http1.h" +#include "h2o/http2.h" +#include "h2o/memcached.h" + +#define USE_HTTPS 0 +#define USE_MEMCACHED 0 + +static h2o_pathconf_t *register_handler(h2o_hostconf_t *hostconf, const char *path, int (*on_req)(h2o_handler_t *, h2o_req_t *)) +{ + h2o_pathconf_t *pathconf = h2o_config_register_path(hostconf, path, 0); + h2o_handler_t *handler = h2o_create_handler(pathconf, sizeof(*handler)); + handler->on_req = on_req; + return pathconf; +} + +static int chunked_test(h2o_handler_t *self, h2o_req_t *req) +{ + static h2o_generator_t generator = {NULL, NULL}; + + if (!h2o_memis(req->method.base, req->method.len, H2O_STRLIT("GET"))) + return -1; + + h2o_iovec_t body = h2o_strdup(&req->pool, "hello world\n", SIZE_MAX); + req->res.status = 200; + req->res.reason = "OK"; + h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, NULL, H2O_STRLIT("text/plain")); + h2o_start_response(req, &generator); + h2o_send(req, &body, 1, 1); + + return 0; +} + +static int reproxy_test(h2o_handler_t *self, h2o_req_t *req) +{ + if (!h2o_memis(req->method.base, req->method.len, H2O_STRLIT("GET"))) + return -1; + + req->res.status = 200; + req->res.reason = "OK"; + h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_X_REPROXY_URL, NULL, H2O_STRLIT("http://www.ietf.org/")); + h2o_send_inline(req, H2O_STRLIT("you should never see this!\n")); + + return 0; +} + +static int post_test(h2o_handler_t *self, h2o_req_t *req) +{ + if (h2o_memis(req->method.base, req->method.len, H2O_STRLIT("POST")) && + h2o_memis(req->path_normalized.base, req->path_normalized.len, H2O_STRLIT("/post-test/"))) { + static h2o_generator_t generator = {NULL, NULL}; + req->res.status = 200; + req->res.reason = "OK"; + h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, NULL, H2O_STRLIT("text/plain; charset=utf-8")); + h2o_start_response(req, &generator); + h2o_send(req, &req->entity, 1, 1); + return 0; + } + + return -1; +} + +static h2o_globalconf_t config; +static h2o_context_t ctx; +static h2o_multithread_receiver_t libmemcached_receiver; +static h2o_accept_ctx_t accept_ctx; + +#if H2O_USE_LIBUV + +static void on_accept(uv_stream_t *listener, int status) +{ + uv_tcp_t *conn; + h2o_socket_t *sock; + + if (status != 0) + return; + + conn = h2o_mem_alloc(sizeof(*conn)); + uv_tcp_init(listener->loop, conn); + + if (uv_accept(listener, (uv_stream_t *)conn) != 0) { + uv_close((uv_handle_t *)conn, (uv_close_cb)free); + return; + } + + sock = h2o_uv_socket_create((uv_stream_t *)conn, (uv_close_cb)free); + h2o_accept(&accept_ctx, sock); +} + +static int create_listener(void) +{ + static uv_tcp_t listener; + struct sockaddr_in addr; + int r; + + uv_tcp_init(ctx.loop, &listener); + uv_ip4_addr("127.0.0.1", 7890, &addr); + if ((r = uv_tcp_bind(&listener, (struct sockaddr *)&addr, 0)) != 0) { + fprintf(stderr, "uv_tcp_bind:%s\n", uv_strerror(r)); + goto Error; + } + if ((r = uv_listen((uv_stream_t *)&listener, 128, on_accept)) != 0) { + fprintf(stderr, "uv_listen:%s\n", uv_strerror(r)); + goto Error; + } + + return 0; +Error: + uv_close((uv_handle_t *)&listener, NULL); + return r; +} + +#else + +static void on_accept(h2o_socket_t *listener, const char *err) +{ + h2o_socket_t *sock; + + if (err != NULL) { + return; + } + + if ((sock = h2o_evloop_socket_accept(listener)) == NULL) + return; + h2o_accept(&accept_ctx, sock); +} + +static int create_listener(void) +{ + struct sockaddr_in addr; + int fd, reuseaddr_flag = 1; + h2o_socket_t *sock; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(0x7f000001); + addr.sin_port = htons(7890); + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 || + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_flag, sizeof(reuseaddr_flag)) != 0 || + bind(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0 || listen(fd, SOMAXCONN) != 0) { + return -1; + } + + sock = h2o_evloop_socket_create(ctx.loop, fd, H2O_SOCKET_FLAG_DONT_READ); + h2o_socket_read_start(sock, on_accept); + + return 0; +} + +#endif + +static int setup_ssl(const char *cert_file, const char *key_file) +{ + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + + accept_ctx.ssl_ctx = SSL_CTX_new(SSLv23_server_method()); + SSL_CTX_set_options(accept_ctx.ssl_ctx, SSL_OP_NO_SSLv2); + + if (USE_MEMCACHED) { + accept_ctx.libmemcached_receiver = &libmemcached_receiver; + h2o_accept_setup_async_ssl_resumption(h2o_memcached_create_context("127.0.0.1", 11211, 0, 1, "h2o:ssl-resumption:"), 86400); + h2o_socket_ssl_async_resumption_setup_ctx(accept_ctx.ssl_ctx); + } + + /* load certificate and private key */ + if (SSL_CTX_use_certificate_file(accept_ctx.ssl_ctx, cert_file, SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "an error occurred while trying to load server certificate file:%s\n", cert_file); + return -1; + } + if (SSL_CTX_use_PrivateKey_file(accept_ctx.ssl_ctx, key_file, SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "an error occurred while trying to load private key file:%s\n", key_file); + return -1; + } + +/* setup protocol negotiation methods */ +#if H2O_USE_NPN + h2o_ssl_register_npn_protocols(accept_ctx.ssl_ctx, h2o_http2_npn_protocols); +#endif +#if H2O_USE_ALPN + h2o_ssl_register_alpn_protocols(accept_ctx.ssl_ctx, h2o_http2_alpn_protocols); +#endif + + return 0; +} + +int main(int argc, char **argv) +{ + h2o_hostconf_t *hostconf; + + signal(SIGPIPE, SIG_IGN); + + h2o_config_init(&config); + hostconf = h2o_config_register_host(&config, h2o_iovec_init(H2O_STRLIT("default")), 65535); + register_handler(hostconf, "/post-test", post_test); + register_handler(hostconf, "/chunked-test", chunked_test); + h2o_reproxy_register(register_handler(hostconf, "/reproxy-test", reproxy_test)); + h2o_file_register(h2o_config_register_path(hostconf, "/", 0), "examples/doc_root", NULL, NULL, 0); + +#if H2O_USE_LIBUV + uv_loop_t loop; + uv_loop_init(&loop); + h2o_context_init(&ctx, &loop, &config); +#else + h2o_context_init(&ctx, h2o_evloop_create(), &config); +#endif + if (USE_MEMCACHED) + h2o_multithread_register_receiver(ctx.queue, &libmemcached_receiver, h2o_memcached_receiver); + + if (USE_HTTPS && setup_ssl("examples/h2o/server.crt", "examples/h2o/server.key") != 0) + goto Error; + + /* disabled by default: uncomment the line below to enable access logging */ + /* h2o_access_log_register(&config.default_host, "/dev/stdout", NULL); */ + + accept_ctx.ctx = &ctx; + accept_ctx.hosts = config.hosts; + + if (create_listener() != 0) { + fprintf(stderr, "failed to listen to 127.0.0.1:7890:%s\n", strerror(errno)); + goto Error; + } + +#if H2O_USE_LIBUV + uv_run(ctx.loop, UV_RUN_DEFAULT); +#else + while (h2o_evloop_run(ctx.loop, INT32_MAX) == 0) + ; +#endif + +Error: + return 1; +} diff --git a/src/web/server/h2o/libh2o/examples/libh2o/socket-client.c b/src/web/server/h2o/libh2o/examples/libh2o/socket-client.c new file mode 100644 index 000000000..591d3896a --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/libh2o/socket-client.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2014 DeNA Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include "h2o/socket.h" +#include "h2o/string_.h" + +static h2o_loop_t *loop; +const char *host; +static SSL_CTX *ssl_ctx; +static int exit_loop; + +static void on_read(h2o_socket_t *sock, const char *err) +{ + if (err != NULL) { + /* read failed */ + fprintf(stderr, "read failed:%s\n", err); + h2o_socket_close(sock); + exit_loop = 1; + return; + } + + fwrite(sock->input->bytes, 1, sock->input->size, stdout); +} + +static void on_write(h2o_socket_t *sock, const char *err) +{ + if (err != NULL) { + /* write failed */ + fprintf(stderr, "write failed:%s\n", err); + h2o_socket_close(sock); + exit_loop = 1; + return; + } + + h2o_socket_read_start(sock, on_read); +} + +static void on_handshake_complete(h2o_socket_t *sock, const char *err) +{ + if (err != NULL) { + /* TLS handshake failed */ + fprintf(stderr, "TLS handshake failure:%s\n", err); + h2o_socket_close(sock); + exit_loop = 1; + return; + } + + h2o_socket_write(sock, sock->data, 1, on_write); +} + +static void on_connect(h2o_socket_t *sock, const char *err) +{ + if (err != NULL) { + /* connection failed */ + fprintf(stderr, "failed to connect to host:%s\n", err); + h2o_socket_close(sock); + exit_loop = 1; + return; + } + + if (ssl_ctx != NULL) { + h2o_socket_ssl_handshake(sock, ssl_ctx, host, on_handshake_complete); + } else { + h2o_socket_write(sock, sock->data, 1, on_write); + } +} + +static void usage(const char *cmd) +{ + fprintf(stderr, "Usage: %s [--tls] \n", cmd); + exit(1); +} + +int main(int argc, char **argv) +{ + struct addrinfo hints, *res = NULL; + int err, ret = 1; + h2o_socket_t *sock; + h2o_iovec_t send_data = {H2O_STRLIT("GET / HTTP/1.0\r\n\r\n")}; + + const char *cmd = (--argc, *argv++); + if (argc < 2) + usage(cmd); + if (strcmp(*argv, "-t") == 0 || strcmp(*argv, "--tls") == 0) { + --argc, ++argv; + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + ssl_ctx = SSL_CTX_new(TLSv1_client_method()); + SSL_CTX_load_verify_locations(ssl_ctx, H2O_TO_STR(H2O_ROOT) "/share/h2o/ca-bundle.crt", NULL); + SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + } + if (argc != 2) + usage(cmd); + host = (--argc, *argv++); + const char *port = (--argc, *argv++); + +#if H2O_USE_LIBUV + loop = uv_loop_new(); +#else + loop = h2o_evloop_create(); +#endif + + /* resolve destination (FIXME use the function supplied by the loop) */ + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_ADDRCONFIG; + if ((err = getaddrinfo(host, port, &hints, &res)) != 0) { + fprintf(stderr, "failed to resolve %s:%s:%s\n", host, port, gai_strerror(err)); + goto Exit; + } + + if ((sock = h2o_socket_connect(loop, res->ai_addr, res->ai_addrlen, on_connect)) == NULL) { + fprintf(stderr, "failed to create socket:%s\n", strerror(errno)); + goto Exit; + } + sock->data = &send_data; + + while (!exit_loop) { +#if H2O_USE_LIBUV + uv_run(loop, UV_RUN_DEFAULT); +#else + h2o_evloop_run(loop, INT32_MAX); +#endif + } + + ret = 0; + +Exit: + if (loop != NULL) { +#if H2O_USE_LIBUV + uv_loop_delete(loop); +#else +// FIXME +// h2o_evloop_destroy(loop); +#endif + } + return ret; +} diff --git a/src/web/server/h2o/libh2o/examples/libh2o/websocket.c b/src/web/server/h2o/libh2o/examples/libh2o/websocket.c new file mode 100644 index 000000000..c977bbd63 --- /dev/null +++ b/src/web/server/h2o/libh2o/examples/libh2o/websocket.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2014 DeNA Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include "h2o.h" +#include "h2o/websocket.h" + +static void on_ws_message(h2o_websocket_conn_t *conn, const struct wslay_event_on_msg_recv_arg *arg) +{ + if (arg == NULL) { + h2o_websocket_close(conn); + return; + } + + if (!wslay_is_ctrl_frame(arg->opcode)) { + struct wslay_event_msg msgarg = {arg->opcode, arg->msg, arg->msg_length}; + wslay_event_queue_msg(conn->ws_ctx, &msgarg); + } +} + +static int on_req(h2o_handler_t *self, h2o_req_t *req) +{ + const char *client_key; + + if (h2o_is_websocket_handshake(req, &client_key) != 0 || client_key == NULL) { + return -1; + } + h2o_upgrade_to_websocket(req, client_key, NULL, on_ws_message); + return 0; +} + +static h2o_globalconf_t config; +static h2o_context_t ctx; +static h2o_accept_ctx_t accept_ctx; + +static void on_connect(uv_stream_t *server, int status) +{ + uv_tcp_t *conn; + h2o_socket_t *sock; + + if (status != 0) + return; + + conn = h2o_mem_alloc(sizeof(*conn)); + uv_tcp_init(server->loop, conn); + if (uv_accept(server, (uv_stream_t *)conn) != 0) { + uv_close((uv_handle_t *)conn, (uv_close_cb)free); + return; + } + + sock = h2o_uv_socket_create((uv_stream_t *)conn, (uv_close_cb)free); + h2o_accept(&accept_ctx, sock); +} + +static int setup_ssl(const char *cert_file, const char *key_file) +{ + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + + accept_ctx.ssl_ctx = SSL_CTX_new(SSLv23_server_method()); + SSL_CTX_set_options(accept_ctx.ssl_ctx, SSL_OP_NO_SSLv2); + + /* load certificate and private key */ + if (SSL_CTX_use_certificate_file(accept_ctx.ssl_ctx, cert_file, SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "an error occurred while trying to load server certificate file:%s\n", cert_file); + return -1; + } + if (SSL_CTX_use_PrivateKey_file(accept_ctx.ssl_ctx, key_file, SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "an error occurred while trying to load private key file:%s\n", key_file); + return -1; + } + + return 0; +} + +int main(int argc, char **argv) +{ + uv_loop_t *loop = uv_default_loop(); + uv_tcp_t listener; + struct sockaddr_in sockaddr; + h2o_hostconf_t *hostconf; + h2o_pathconf_t *pathconf; + int r; + + if ((r = uv_tcp_init(loop, &listener)) != 0) { + fprintf(stderr, "uv_tcp_init:%s\n", uv_strerror(r)); + goto Error; + } + uv_ip4_addr("127.0.0.1", 7890, &sockaddr); + if ((r = uv_tcp_bind(&listener, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) != 0) { + fprintf(stderr, "uv_tcp_bind:%s\n", uv_strerror(r)); + goto Error; + } + if ((r = uv_listen((uv_stream_t *)&listener, 128, on_connect)) != 0) { + fprintf(stderr, "uv_listen:%s\n", uv_strerror(r)); + goto Error; + } + + h2o_config_init(&config); + hostconf = h2o_config_register_host(&config, h2o_iovec_init(H2O_STRLIT("default")), 65535); + pathconf = h2o_config_register_path(hostconf, "/", 0); + h2o_create_handler(pathconf, sizeof(h2o_handler_t))->on_req = on_req; + + h2o_context_init(&ctx, loop, &config); + + /* disabled by default: uncomment the block below to use HTTPS instead of HTTP */ + /* + if (setup_ssl("server.crt", "server.key") != 0) + goto Error; + */ + + accept_ctx.ctx = &ctx; + accept_ctx.hosts = config.hosts; + + return uv_run(loop, UV_RUN_DEFAULT); + +Error: + return 1; +} -- cgit v1.2.3