summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/lib
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 12:08:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 12:08:18 +0000
commit5da14042f70711ea5cf66e034699730335462f66 (patch)
tree0f6354ccac934ed87a2d555f45be4c831cf92f4a /web/server/h2o/libh2o/lib
parentReleasing debian version 1.44.3-2. (diff)
downloadnetdata-5da14042f70711ea5cf66e034699730335462f66.tar.xz
netdata-5da14042f70711ea5cf66e034699730335462f66.zip
Merging upstream version 1.45.3+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'web/server/h2o/libh2o/lib')
-rw-r--r--web/server/h2o/libh2o/lib/common/cache.c273
-rw-r--r--web/server/h2o/libh2o/lib/common/file.c68
-rw-r--r--web/server/h2o/libh2o/lib/common/filecache.c170
-rw-r--r--web/server/h2o/libh2o/lib/common/hostinfo.c229
-rw-r--r--web/server/h2o/libh2o/lib/common/http1client.c582
-rw-r--r--web/server/h2o/libh2o/lib/common/memcached.c429
-rw-r--r--web/server/h2o/libh2o/lib/common/memory.c400
-rw-r--r--web/server/h2o/libh2o/lib/common/multithread.c274
-rw-r--r--web/server/h2o/libh2o/lib/common/serverutil.c317
-rw-r--r--web/server/h2o/libh2o/lib/common/socket.c1433
-rw-r--r--web/server/h2o/libh2o/lib/common/socket/evloop.c.h624
-rw-r--r--web/server/h2o/libh2o/lib/common/socket/evloop/epoll.c.h203
-rw-r--r--web/server/h2o/libh2o/lib/common/socket/evloop/kqueue.c.h186
-rw-r--r--web/server/h2o/libh2o/lib/common/socket/evloop/poll.c.h178
-rw-r--r--web/server/h2o/libh2o/lib/common/socket/uv-binding.c.h283
-rw-r--r--web/server/h2o/libh2o/lib/common/socketpool.c342
-rw-r--r--web/server/h2o/libh2o/lib/common/string.c594
-rw-r--r--web/server/h2o/libh2o/lib/common/time.c175
-rw-r--r--web/server/h2o/libh2o/lib/common/timeout.c90
-rw-r--r--web/server/h2o/libh2o/lib/common/url.c409
-rw-r--r--web/server/h2o/libh2o/lib/core/config.c325
-rw-r--r--web/server/h2o/libh2o/lib/core/configurator.c1102
-rw-r--r--web/server/h2o/libh2o/lib/core/context.c201
-rw-r--r--web/server/h2o/libh2o/lib/core/headers.c155
-rw-r--r--web/server/h2o/libh2o/lib/core/logconf.c793
-rw-r--r--web/server/h2o/libh2o/lib/core/proxy.c610
-rw-r--r--web/server/h2o/libh2o/lib/core/request.c696
-rw-r--r--web/server/h2o/libh2o/lib/core/token.c28
-rw-r--r--web/server/h2o/libh2o/lib/core/token_table.h408
-rw-r--r--web/server/h2o/libh2o/lib/core/util.c562
-rw-r--r--web/server/h2o/libh2o/lib/handler/access_log.c153
-rw-r--r--web/server/h2o/libh2o/lib/handler/chunked.c113
-rw-r--r--web/server/h2o/libh2o/lib/handler/compress.c144
-rw-r--r--web/server/h2o/libh2o/lib/handler/compress/brotli.cc138
-rw-r--r--web/server/h2o/libh2o/lib/handler/compress/gzip.c190
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/access_log.c143
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/compress.c172
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/errordoc.c203
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/expires.c123
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/fastcgi.c388
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/file.c197
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/headers.c74
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/headers_util.c143
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/http2_debug_state.c46
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/mruby.c177
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/proxy.c392
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/redirect.c76
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/reproxy.c81
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/status.c87
-rw-r--r--web/server/h2o/libh2o/lib/handler/configurator/throttle_resp.c73
-rw-r--r--web/server/h2o/libh2o/lib/handler/errordoc.c145
-rw-r--r--web/server/h2o/libh2o/lib/handler/expires.c84
-rw-r--r--web/server/h2o/libh2o/lib/handler/fastcgi.c856
-rw-r--r--web/server/h2o/libh2o/lib/handler/file.c966
-rw-r--r--web/server/h2o/libh2o/lib/handler/file/_templates.c.h90
-rw-r--r--web/server/h2o/libh2o/lib/handler/file/templates.c.h171
-rw-r--r--web/server/h2o/libh2o/lib/handler/headers.c58
-rw-r--r--web/server/h2o/libh2o/lib/handler/headers_util.c114
-rw-r--r--web/server/h2o/libh2o/lib/handler/http2_debug_state.c69
-rw-r--r--web/server/h2o/libh2o/lib/handler/mimemap.c419
-rw-r--r--web/server/h2o/libh2o/lib/handler/mimemap/defaults.c.h109
-rw-r--r--web/server/h2o/libh2o/lib/handler/mruby.c938
-rw-r--r--web/server/h2o/libh2o/lib/handler/mruby/chunked.c270
-rw-r--r--web/server/h2o/libh2o/lib/handler/mruby/embedded.c.h111
-rw-r--r--web/server/h2o/libh2o/lib/handler/mruby/embedded/chunked.rb35
-rw-r--r--web/server/h2o/libh2o/lib/handler/mruby/embedded/core.rb81
-rw-r--r--web/server/h2o/libh2o/lib/handler/mruby/embedded/http_request.rb54
-rw-r--r--web/server/h2o/libh2o/lib/handler/mruby/http_request.c500
-rw-r--r--web/server/h2o/libh2o/lib/handler/proxy.c165
-rw-r--r--web/server/h2o/libh2o/lib/handler/redirect.c106
-rw-r--r--web/server/h2o/libh2o/lib/handler/reproxy.c66
-rw-r--r--web/server/h2o/libh2o/lib/handler/status.c270
-rw-r--r--web/server/h2o/libh2o/lib/handler/status/durations.c207
-rw-r--r--web/server/h2o/libh2o/lib/handler/status/events.c112
-rw-r--r--web/server/h2o/libh2o/lib/handler/status/requests.c151
-rw-r--r--web/server/h2o/libh2o/lib/handler/throttle_resp.c156
-rw-r--r--web/server/h2o/libh2o/lib/http1.c859
-rw-r--r--web/server/h2o/libh2o/lib/http2/cache_digests.c201
-rw-r--r--web/server/h2o/libh2o/lib/http2/casper.c205
-rw-r--r--web/server/h2o/libh2o/lib/http2/connection.c1419
-rw-r--r--web/server/h2o/libh2o/lib/http2/frame.c290
-rw-r--r--web/server/h2o/libh2o/lib/http2/hpack.c917
-rw-r--r--web/server/h2o/libh2o/lib/http2/hpack_huffman_table.h4954
-rw-r--r--web/server/h2o/libh2o/lib/http2/hpack_static_table.h87
-rw-r--r--web/server/h2o/libh2o/lib/http2/http2_debug_state.c194
-rw-r--r--web/server/h2o/libh2o/lib/http2/scheduler.c365
-rw-r--r--web/server/h2o/libh2o/lib/http2/stream.c410
-rw-r--r--web/server/h2o/libh2o/lib/tunnel.c138
-rw-r--r--web/server/h2o/libh2o/lib/websocket.c238
89 files changed, 0 insertions, 31832 deletions
diff --git a/web/server/h2o/libh2o/lib/common/cache.c b/web/server/h2o/libh2o/lib/common/cache.c
deleted file mode 100644
index cc8d8f007..000000000
--- a/web/server/h2o/libh2o/lib/common/cache.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <assert.h>
-#include <pthread.h>
-#include "khash.h"
-#include "h2o/cache.h"
-#include "h2o/linklist.h"
-#include "h2o/memory.h"
-#include "h2o/string_.h"
-
-static h2o_cache_hashcode_t get_keyhash(h2o_cache_ref_t *ref);
-static int is_equal(h2o_cache_ref_t *x, h2o_cache_ref_t *y);
-
-KHASH_INIT(cache, h2o_cache_ref_t *, char, 0, get_keyhash, is_equal)
-
-struct st_h2o_cache_t {
- int flags;
- khash_t(cache) * table;
- size_t size;
- size_t capacity;
- h2o_linklist_t lru;
- h2o_linklist_t age;
- uint64_t duration;
- void (*destroy_cb)(h2o_iovec_t value);
- pthread_mutex_t mutex; /* only used if (flags & H2O_CACHE_FLAG_MULTITHREADED) != 0 */
-};
-
-static h2o_cache_hashcode_t get_keyhash(h2o_cache_ref_t *ref)
-{
- return ref->keyhash;
-}
-
-static int is_equal(h2o_cache_ref_t *x, h2o_cache_ref_t *y)
-{
- return x->key.len == y->key.len && memcmp(x->key.base, y->key.base, x->key.len) == 0;
-}
-
-static void lock_cache(h2o_cache_t *cache)
-{
- if ((cache->flags & H2O_CACHE_FLAG_MULTITHREADED) != 0)
- pthread_mutex_lock(&cache->mutex);
-}
-
-static void unlock_cache(h2o_cache_t *cache)
-{
- if ((cache->flags & H2O_CACHE_FLAG_MULTITHREADED) != 0)
- pthread_mutex_unlock(&cache->mutex);
-}
-
-static void erase_ref(h2o_cache_t *cache, khiter_t iter, int reuse)
-{
- h2o_cache_ref_t *ref = kh_key(cache->table, iter);
-
- if (!reuse)
- kh_del(cache, cache->table, iter);
- h2o_linklist_unlink(&ref->_lru_link);
- h2o_linklist_unlink(&ref->_age_link);
- cache->size -= ref->value.len;
-
- h2o_cache_release(cache, ref);
-}
-
-static int64_t get_timeleft(h2o_cache_t *cache, h2o_cache_ref_t *ref, uint64_t now)
-{
- return (int64_t)(ref->at + cache->duration) - now;
-}
-
-static void purge(h2o_cache_t *cache, uint64_t now)
-{
- /* by cache size */
- while (cache->capacity < cache->size) {
- h2o_cache_ref_t *last;
- assert(!h2o_linklist_is_empty(&cache->lru));
- last = H2O_STRUCT_FROM_MEMBER(h2o_cache_ref_t, _lru_link, cache->lru.next);
- erase_ref(cache, kh_get(cache, cache->table, last), 0);
- }
- /* by TTL */
- while (!h2o_linklist_is_empty(&cache->age)) {
- h2o_cache_ref_t *oldest = H2O_STRUCT_FROM_MEMBER(h2o_cache_ref_t, _age_link, cache->age.next);
- if (get_timeleft(cache, oldest, now) >= 0)
- break;
- erase_ref(cache, kh_get(cache, cache->table, oldest), 0);
- }
-}
-
-h2o_cache_hashcode_t h2o_cache_calchash(const char *s, size_t l)
-{
- h2o_cache_hashcode_t h = 0;
- for (; l != 0; --l)
- h = (h << 5) - h + ((unsigned char *)s)[l - 1];
- return h;
-}
-
-h2o_cache_t *h2o_cache_create(int flags, size_t capacity, uint64_t duration, void (*destroy_cb)(h2o_iovec_t value))
-{
- h2o_cache_t *cache = h2o_mem_alloc(sizeof(*cache));
-
- cache->flags = flags;
- cache->table = kh_init(cache);
- cache->size = 0;
- cache->capacity = capacity;
- h2o_linklist_init_anchor(&cache->lru);
- h2o_linklist_init_anchor(&cache->age);
- cache->duration = duration;
- cache->destroy_cb = destroy_cb;
- if ((cache->flags & H2O_CACHE_FLAG_MULTITHREADED) != 0)
- pthread_mutex_init(&cache->mutex, NULL);
-
- return cache;
-}
-
-void h2o_cache_destroy(h2o_cache_t *cache)
-{
- h2o_cache_clear(cache);
- kh_destroy(cache, cache->table);
- if ((cache->flags & H2O_CACHE_FLAG_MULTITHREADED) != 0)
- pthread_mutex_destroy(&cache->mutex);
- free(cache);
-}
-
-void h2o_cache_clear(h2o_cache_t *cache)
-{
- lock_cache(cache);
-
- while (!h2o_linklist_is_empty(&cache->lru)) {
- h2o_cache_ref_t *ref = H2O_STRUCT_FROM_MEMBER(h2o_cache_ref_t, _lru_link, cache->lru.next);
- erase_ref(cache, kh_get(cache, cache->table, ref), 0);
- }
- assert(h2o_linklist_is_linked(&cache->age));
- assert(kh_size(cache->table) == 0);
- assert(cache->size == 0);
-
- unlock_cache(cache);
-}
-
-h2o_cache_ref_t *h2o_cache_fetch(h2o_cache_t *cache, uint64_t now, h2o_iovec_t key, h2o_cache_hashcode_t keyhash)
-{
- h2o_cache_ref_t search_key, *ref;
- khiter_t iter;
- int64_t timeleft;
-
- if (keyhash == 0)
- keyhash = h2o_cache_calchash(key.base, key.len);
- search_key.key = key;
- search_key.keyhash = keyhash;
-
- lock_cache(cache);
-
- purge(cache, now);
-
- if ((iter = kh_get(cache, cache->table, &search_key)) == kh_end(cache->table))
- goto NotFound;
-
- /* found */
- ref = kh_key(cache->table, iter);
- timeleft = get_timeleft(cache, ref, now);
- if (timeleft < 0)
- goto NotFound;
- if ((cache->flags & H2O_CACHE_FLAG_EARLY_UPDATE) != 0 && timeleft < 10 && !ref->_requested_early_update) {
- ref->_requested_early_update = 1;
- goto NotFound;
- }
- /* move the entry to the top of LRU */
- h2o_linklist_unlink(&ref->_lru_link);
- h2o_linklist_insert(&cache->lru, &ref->_lru_link);
- __sync_fetch_and_add(&ref->_refcnt, 1);
-
- /* unlock and return the found entry */
- unlock_cache(cache);
- return ref;
-
-NotFound:
- unlock_cache(cache);
- return NULL;
-}
-
-void h2o_cache_release(h2o_cache_t *cache, h2o_cache_ref_t *ref)
-{
- if (__sync_fetch_and_sub(&ref->_refcnt, 1) == 1) {
- assert(!h2o_linklist_is_linked(&ref->_lru_link));
- assert(!h2o_linklist_is_linked(&ref->_age_link));
- if (cache->destroy_cb != NULL)
- cache->destroy_cb(ref->value);
- free(ref->key.base);
- free(ref);
- }
-}
-
-int h2o_cache_set(h2o_cache_t *cache, uint64_t now, h2o_iovec_t key, h2o_cache_hashcode_t keyhash, h2o_iovec_t value)
-{
- h2o_cache_ref_t *newref;
- khiter_t iter;
- int existed;
-
- if (keyhash == 0)
- keyhash = h2o_cache_calchash(key.base, key.len);
-
- /* create newref */
- newref = h2o_mem_alloc(sizeof(*newref));
- *newref = (h2o_cache_ref_t){h2o_strdup(NULL, key.base, key.len), keyhash, now, value, 0, {NULL}, {NULL}, 1};
-
- lock_cache(cache);
-
- /* set or replace the named value */
- iter = kh_get(cache, cache->table, newref);
- if (iter != kh_end(cache->table)) {
- erase_ref(cache, iter, 1);
- kh_key(cache->table, iter) = newref;
- existed = 1;
- } else {
- int unused;
- kh_put(cache, cache->table, newref, &unused);
- existed = 0;
- }
- h2o_linklist_insert(&cache->lru, &newref->_lru_link);
- h2o_linklist_insert(&cache->age, &newref->_age_link);
- cache->size += newref->value.len;
-
- purge(cache, now);
-
- unlock_cache(cache);
-
- return existed;
-}
-
-void h2o_cache_delete(h2o_cache_t *cache, uint64_t now, h2o_iovec_t key, h2o_cache_hashcode_t keyhash)
-{
- h2o_cache_ref_t search_key;
- khiter_t iter;
-
- if (keyhash == 0)
- keyhash = h2o_cache_calchash(key.base, key.len);
- search_key.key = key;
- search_key.keyhash = keyhash;
-
- lock_cache(cache);
-
- purge(cache, now);
-
- if ((iter = kh_get(cache, cache->table, &search_key)) != kh_end(cache->table))
- erase_ref(cache, iter, 0);
-
- unlock_cache(cache);
-}
-
-size_t h2o_cache_get_capacity(h2o_cache_t *cache)
-{
- return cache->capacity;
-}
-
-uint64_t h2o_cache_get_duration(h2o_cache_t *cache)
-{
- return cache->duration;
-}
diff --git a/web/server/h2o/libh2o/lib/common/file.c b/web/server/h2o/libh2o/lib/common/file.c
deleted file mode 100644
index 3cf5ac5d1..000000000
--- a/web/server/h2o/libh2o/lib/common/file.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <errno.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include "h2o/file.h"
-
-h2o_iovec_t h2o_file_read(const char *fn)
-{
- int fd;
- struct stat st;
- h2o_iovec_t ret = {NULL};
-
- /* open */
- if ((fd = open(fn, O_RDONLY | O_CLOEXEC)) == -1)
- goto Error;
- if (fstat(fd, &st))
- goto Error;
- /* allocate memory */
- if (st.st_size > SIZE_MAX) {
- errno = ENOMEM;
- goto Error;
- }
- if ((ret.base = malloc((size_t)st.st_size)) == NULL)
- goto Error;
- /* read */
- while (ret.len != (size_t)st.st_size) {
- ssize_t r;
- while ((r = read(fd, ret.base + ret.len, (size_t)st.st_size - ret.len)) == -1 && errno == EINTR)
- ;
- if (r <= 0)
- goto Error;
- ret.len += r;
- }
- /* close */
- close(fd);
- return ret;
-
-Error:
- if (fd != -1)
- close(fd);
- free(ret.base);
- return (h2o_iovec_t){NULL};
-}
diff --git a/web/server/h2o/libh2o/lib/common/filecache.c b/web/server/h2o/libh2o/lib/common/filecache.c
deleted file mode 100644
index 747a1ffa6..000000000
--- a/web/server/h2o/libh2o/lib/common/filecache.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <unistd.h>
-#include "khash.h"
-#include "h2o/memory.h"
-#include "h2o/filecache.h"
-
-KHASH_SET_INIT_STR(opencache_set)
-
-struct st_h2o_filecache_t {
- khash_t(opencache_set) * hash;
- h2o_linklist_t lru;
- size_t capacity;
-};
-
-static inline void release_from_cache(h2o_filecache_t *cache, khiter_t iter)
-{
- const char *path = kh_key(cache->hash, iter);
- h2o_filecache_ref_t *ref = H2O_STRUCT_FROM_MEMBER(h2o_filecache_ref_t, _path, path);
-
- /* detach from list */
- kh_del(opencache_set, cache->hash, iter);
- h2o_linklist_unlink(&ref->_lru);
-
- /* and close */
- h2o_filecache_close_file(ref);
-}
-
-h2o_filecache_t *h2o_filecache_create(size_t capacity)
-{
- h2o_filecache_t *cache = h2o_mem_alloc(sizeof(*cache));
-
- cache->hash = kh_init(opencache_set);
- h2o_linklist_init_anchor(&cache->lru);
- cache->capacity = capacity;
-
- return cache;
-}
-
-void h2o_filecache_destroy(h2o_filecache_t *cache)
-{
- h2o_filecache_clear(cache);
- assert(kh_size(cache->hash) == 0);
- assert(h2o_linklist_is_empty(&cache->lru));
- kh_destroy(opencache_set, cache->hash);
- free(cache);
-}
-
-void h2o_filecache_clear(h2o_filecache_t *cache)
-{
- khiter_t iter;
- for (iter = kh_begin(cache->hash); iter != kh_end(cache->hash); ++iter) {
- if (!kh_exist(cache->hash, iter))
- continue;
- release_from_cache(cache, iter);
- }
- assert(kh_size(cache->hash) == 0);
-}
-
-h2o_filecache_ref_t *h2o_filecache_open_file(h2o_filecache_t *cache, const char *path, int oflag)
-{
- khiter_t iter = kh_get(opencache_set, cache->hash, path);
- h2o_filecache_ref_t *ref;
- int dummy;
-
- /* lookup cache, and return the one if found */
- if (iter != kh_end(cache->hash)) {
- ref = H2O_STRUCT_FROM_MEMBER(h2o_filecache_ref_t, _path, kh_key(cache->hash, iter));
- ++ref->_refcnt;
- goto Exit;
- }
-
- /* create a new cache entry */
- ref = h2o_mem_alloc(offsetof(h2o_filecache_ref_t, _path) + strlen(path) + 1);
- ref->_refcnt = 1;
- ref->_lru = (h2o_linklist_t){NULL};
- strcpy(ref->_path, path);
-
- /* if cache is used, then... */
- if (cache->capacity != 0) {
- /* purge one entry from LRU if cache is full */
- if (kh_size(cache->hash) == cache->capacity) {
- h2o_filecache_ref_t *purge_ref = H2O_STRUCT_FROM_MEMBER(h2o_filecache_ref_t, _lru, cache->lru.prev);
- khiter_t purge_iter = kh_get(opencache_set, cache->hash, purge_ref->_path);
- assert(purge_iter != kh_end(cache->hash));
- release_from_cache(cache, purge_iter);
- }
- /* assign the new entry */
- ++ref->_refcnt;
- kh_put(opencache_set, cache->hash, ref->_path, &dummy);
- h2o_linklist_insert(cache->lru.next, &ref->_lru);
- }
-
- /* open the file, or memoize the error */
- if ((ref->fd = open(path, oflag)) != -1 && fstat(ref->fd, &ref->st) == 0) {
- ref->_last_modified.str[0] = '\0';
- ref->_etag.len = 0;
- } else {
- ref->open_err = errno;
- if (ref->fd != -1) {
- close(ref->fd);
- ref->fd = -1;
- }
- }
-
-Exit:
- /* if the cache entry retains an error, return it instead of the reference */
- if (ref->fd == -1) {
- errno = ref->open_err;
- h2o_filecache_close_file(ref);
- ref = NULL;
- }
- return ref;
-}
-
-void h2o_filecache_close_file(h2o_filecache_ref_t *ref)
-{
- if (--ref->_refcnt != 0)
- return;
- assert(!h2o_linklist_is_linked(&ref->_lru));
- if (ref->fd != -1) {
- close(ref->fd);
- ref->fd = -1;
- }
- free(ref);
-}
-
-struct tm *h2o_filecache_get_last_modified(h2o_filecache_ref_t *ref, char *outbuf)
-{
- assert(ref->fd != -1);
- if (ref->_last_modified.str[0] == '\0') {
- gmtime_r(&ref->st.st_mtime, &ref->_last_modified.gm);
- h2o_time2str_rfc1123(ref->_last_modified.str, &ref->_last_modified.gm);
- }
- if (outbuf != NULL)
- memcpy(outbuf, ref->_last_modified.str, H2O_TIMESTR_RFC1123_LEN + 1);
- return &ref->_last_modified.gm;
-}
-
-size_t h2o_filecache_get_etag(h2o_filecache_ref_t *ref, char *outbuf)
-{
- assert(ref->fd != -1);
- if (ref->_etag.len == 0)
- ref->_etag.len = sprintf(ref->_etag.buf, "\"%08x-%zx\"", (unsigned)ref->st.st_mtime, (size_t)ref->st.st_size);
- memcpy(outbuf, ref->_etag.buf, ref->_etag.len + 1);
- return ref->_etag.len;
-}
diff --git a/web/server/h2o/libh2o/lib/common/hostinfo.c b/web/server/h2o/libh2o/lib/common/hostinfo.c
deleted file mode 100644
index 7b481e296..000000000
--- a/web/server/h2o/libh2o/lib/common/hostinfo.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 "h2o/hostinfo.h"
-
-struct st_h2o_hostinfo_getaddr_req_t {
- h2o_multithread_receiver_t *_receiver;
- h2o_hostinfo_getaddr_cb _cb;
- void *cbdata;
- h2o_linklist_t _pending;
- union {
- struct {
- char *name;
- char *serv;
- struct addrinfo hints;
- } _in;
- struct {
- h2o_multithread_message_t message;
- const char *errstr;
- struct addrinfo *ai;
- } _out;
- };
-};
-
-static struct {
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- h2o_linklist_t pending; /* anchor of h2o_hostinfo_getaddr_req_t::_pending */
- size_t num_threads;
- size_t num_threads_idle;
-} queue = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, {&queue.pending, &queue.pending}, 0, 0};
-
-size_t h2o_hostinfo_max_threads = 1;
-
-static void lookup_and_respond(h2o_hostinfo_getaddr_req_t *req)
-{
- struct addrinfo *res;
-
- int ret = getaddrinfo(req->_in.name, req->_in.serv, &req->_in.hints, &res);
- req->_out.message = (h2o_multithread_message_t){{NULL}};
- if (ret != 0) {
- req->_out.errstr = gai_strerror(ret);
- req->_out.ai = NULL;
- } else {
- req->_out.errstr = NULL;
- req->_out.ai = res;
- }
-
- h2o_multithread_send_message(req->_receiver, &req->_out.message);
-}
-
-static void *lookup_thread_main(void *_unused)
-{
- pthread_mutex_lock(&queue.mutex);
-
- while (1) {
- --queue.num_threads_idle;
- while (!h2o_linklist_is_empty(&queue.pending)) {
- h2o_hostinfo_getaddr_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_hostinfo_getaddr_req_t, _pending, queue.pending.next);
- h2o_linklist_unlink(&req->_pending);
- pthread_mutex_unlock(&queue.mutex);
- lookup_and_respond(req);
- pthread_mutex_lock(&queue.mutex);
- }
- ++queue.num_threads_idle;
- pthread_cond_wait(&queue.cond, &queue.mutex);
- }
-
- h2o_fatal("unreachable");
- return NULL;
-}
-
-static void create_lookup_thread(void)
-{
- pthread_t tid;
- pthread_attr_t attr;
- int ret;
-
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, 1);
- pthread_attr_setstacksize(&attr, 100 * 1024);
- if ((ret = pthread_create(&tid, NULL, lookup_thread_main, NULL)) != 0) {
- if (queue.num_threads == 0) {
- fprintf(stderr, "failed to start first thread for getaddrinfo:%s\n", strerror(ret));
- abort();
- } else {
- perror("pthread_create(for getaddrinfo)");
- }
- return;
- }
-
- ++queue.num_threads;
- ++queue.num_threads_idle;
-}
-
-h2o_hostinfo_getaddr_req_t *h2o_hostinfo_getaddr(h2o_multithread_receiver_t *receiver, h2o_iovec_t name, h2o_iovec_t serv,
- int family, int socktype, int protocol, int flags, h2o_hostinfo_getaddr_cb cb,
- void *cbdata)
-{
- h2o_hostinfo_getaddr_req_t *req = h2o_mem_alloc(sizeof(*req) + name.len + 1 + serv.len + 1);
- req->_receiver = receiver;
- req->_cb = cb;
- req->cbdata = cbdata;
- req->_pending = (h2o_linklist_t){NULL};
- req->_in.name = (char *)req + sizeof(*req);
- memcpy(req->_in.name, name.base, name.len);
- req->_in.name[name.len] = '\0';
- req->_in.serv = req->_in.name + name.len + 1;
- memcpy(req->_in.serv, serv.base, serv.len);
- req->_in.serv[serv.len] = '\0';
- memset(&req->_in.hints, 0, sizeof(req->_in.hints));
- req->_in.hints.ai_family = family;
- req->_in.hints.ai_socktype = socktype;
- req->_in.hints.ai_protocol = protocol;
- req->_in.hints.ai_flags = flags;
-
- h2o__hostinfo_getaddr_dispatch(req);
-
- return req;
-}
-
-void h2o__hostinfo_getaddr_dispatch(h2o_hostinfo_getaddr_req_t *req)
-{
- pthread_mutex_lock(&queue.mutex);
-
- h2o_linklist_insert(&queue.pending, &req->_pending);
-
- if (queue.num_threads_idle == 0 && queue.num_threads < h2o_hostinfo_max_threads)
- create_lookup_thread();
-
- pthread_cond_signal(&queue.cond);
- pthread_mutex_unlock(&queue.mutex);
-}
-
-void h2o_hostinfo_getaddr_cancel(h2o_hostinfo_getaddr_req_t *req)
-{
- int should_free = 0;
-
- pthread_mutex_lock(&queue.mutex);
-
- if (h2o_linklist_is_linked(&req->_pending)) {
- h2o_linklist_unlink(&req->_pending);
- should_free = 1;
- } else {
- req->_cb = NULL;
- }
-
- pthread_mutex_unlock(&queue.mutex);
-
- if (should_free)
- free(req);
-}
-
-void h2o_hostinfo_getaddr_receiver(h2o_multithread_receiver_t *receiver, h2o_linklist_t *messages)
-{
- while (!h2o_linklist_is_empty(messages)) {
- h2o_hostinfo_getaddr_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_hostinfo_getaddr_req_t, _out.message.link, messages->next);
- h2o_linklist_unlink(&req->_out.message.link);
- h2o_hostinfo_getaddr_cb cb = req->_cb;
- if (cb != NULL) {
- req->_cb = NULL;
- cb(req, req->_out.errstr, req->_out.ai, req->cbdata);
- }
- if (req->_out.ai != NULL)
- freeaddrinfo(req->_out.ai);
- free(req);
- }
-}
-
-static const char *fetch_aton_digit(const char *p, const char *end, unsigned char *value)
-{
- size_t ndigits = 0;
- int v = 0;
-
- while (p != end && ('0' <= *p && *p <= '9')) {
- v = v * 10 + *p++ - '0';
- ++ndigits;
- }
- if (!(1 <= ndigits && ndigits <= 3))
- return NULL;
- if (v > 255)
- return NULL;
- *value = (unsigned char)v;
- return p;
-}
-
-int h2o_hostinfo_aton(h2o_iovec_t host, struct in_addr *addr)
-{
- union {
- int32_t n;
- unsigned char c[4];
- } value;
- const char *p = host.base, *end = p + host.len;
- size_t ndots = 0;
-
- while (1) {
- if ((p = fetch_aton_digit(p, end, value.c + ndots)) == NULL)
- return -1;
- if (ndots == 3)
- break;
- if (p == end || !(*p == '.'))
- return -1;
- ++p;
- ++ndots;
- }
- if (p != end)
- return -1;
-
- addr->s_addr = value.n;
- return 0;
-}
diff --git a/web/server/h2o/libh2o/lib/common/http1client.c b/web/server/h2o/libh2o/lib/common/http1client.c
deleted file mode 100644
index 8547ea817..000000000
--- a/web/server/h2o/libh2o/lib/common/http1client.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * 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 <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include "picohttpparser.h"
-#include "h2o.h"
-
-struct st_h2o_http1client_private_t {
- h2o_http1client_t super;
- union {
- h2o_http1client_connect_cb on_connect;
- h2o_http1client_head_cb on_head;
- h2o_http1client_body_cb on_body;
- } _cb;
- h2o_timeout_entry_t _timeout;
- int _method_is_head;
- h2o_hostinfo_getaddr_req_t *_getaddr_req;
- int _can_keepalive;
- union {
- struct {
- size_t bytesleft;
- } content_length;
- struct {
- struct phr_chunked_decoder decoder;
- size_t bytes_decoded_in_buf;
- } chunked;
- } _body_decoder;
-};
-
-static void close_client(struct st_h2o_http1client_private_t *client)
-{
- if (client->_getaddr_req != NULL) {
- h2o_hostinfo_getaddr_cancel(client->_getaddr_req);
- client->_getaddr_req = NULL;
- }
- if (client->super.ssl.server_name != NULL)
- free(client->super.ssl.server_name);
- if (client->super.sock != NULL) {
- if (client->super.sockpool.pool != NULL && client->_can_keepalive) {
- /* we do not send pipelined requests, and thus can trash all the received input at the end of the request */
- h2o_buffer_consume(&client->super.sock->input, client->super.sock->input->size);
- h2o_socketpool_return(client->super.sockpool.pool, client->super.sock);
- } else {
- h2o_socket_close(client->super.sock);
- }
- } else {
- if (client->super.sockpool.connect_req != NULL) {
- h2o_socketpool_cancel_connect(client->super.sockpool.connect_req);
- client->super.sockpool.connect_req = NULL;
- }
- }
- if (h2o_timeout_is_linked(&client->_timeout))
- h2o_timeout_unlink(&client->_timeout);
- free(client);
-}
-
-static void on_body_error(struct st_h2o_http1client_private_t *client, const char *errstr)
-{
- client->_can_keepalive = 0;
- client->_cb.on_body(&client->super, errstr);
- close_client(client);
-}
-
-static void on_body_timeout(h2o_timeout_entry_t *entry)
-{
- struct st_h2o_http1client_private_t *client = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1client_private_t, _timeout, entry);
- on_body_error(client, "I/O timeout");
-}
-
-static void on_body_until_close(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1client_private_t *client = sock->data;
-
- h2o_timeout_unlink(&client->_timeout);
-
- if (err != NULL) {
- client->_cb.on_body(&client->super, h2o_http1client_error_is_eos);
- close_client(client);
- return;
- }
-
- if (sock->bytes_read != 0) {
- if (client->_cb.on_body(&client->super, NULL) != 0) {
- close_client(client);
- return;
- }
- }
-
- h2o_timeout_link(client->super.ctx->loop, client->super.ctx->io_timeout, &client->_timeout);
-}
-
-static void on_body_content_length(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1client_private_t *client = sock->data;
-
- h2o_timeout_unlink(&client->_timeout);
-
- if (err != NULL) {
- on_body_error(client, "I/O error (body; content-length)");
- return;
- }
-
- if (sock->bytes_read != 0 || client->_body_decoder.content_length.bytesleft == 0) {
- const char *errstr;
- int ret;
- if (client->_body_decoder.content_length.bytesleft <= sock->bytes_read) {
- if (client->_body_decoder.content_length.bytesleft < sock->bytes_read) {
- /* remove the trailing garbage from buf, and disable keepalive */
- client->super.sock->input->size -= sock->bytes_read - client->_body_decoder.content_length.bytesleft;
- client->_can_keepalive = 0;
- }
- client->_body_decoder.content_length.bytesleft = 0;
- errstr = h2o_http1client_error_is_eos;
- } else {
- client->_body_decoder.content_length.bytesleft -= sock->bytes_read;
- errstr = NULL;
- }
- ret = client->_cb.on_body(&client->super, errstr);
- if (errstr == h2o_http1client_error_is_eos) {
- close_client(client);
- return;
- } else if (ret != 0) {
- client->_can_keepalive = 0;
- close_client(client);
- return;
- }
- }
-
- h2o_timeout_link(client->super.ctx->loop, client->super.ctx->io_timeout, &client->_timeout);
-}
-
-static void on_body_chunked(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1client_private_t *client = sock->data;
- h2o_buffer_t *inbuf;
-
- h2o_timeout_unlink(&client->_timeout);
-
- if (err != NULL) {
- if (err == h2o_socket_error_closed && !phr_decode_chunked_is_in_data(&client->_body_decoder.chunked.decoder)) {
- /*
- * if the peer closed after a full chunk, treat this
- * as if the transfer had complete, browsers appear to ignore
- * a missing 0\r\n chunk
- */
- client->_can_keepalive = 0;
- client->_cb.on_body(&client->super, h2o_http1client_error_is_eos);
- close_client(client);
- } else {
- on_body_error(client, "I/O error (body; chunked)");
- }
- return;
- }
-
- inbuf = client->super.sock->input;
- if (sock->bytes_read != 0) {
- const char *errstr;
- int cb_ret;
- size_t newsz = sock->bytes_read;
- switch (phr_decode_chunked(&client->_body_decoder.chunked.decoder, inbuf->bytes + inbuf->size - newsz, &newsz)) {
- case -1: /* error */
- newsz = sock->bytes_read;
- client->_can_keepalive = 0;
- errstr = "failed to parse the response (chunked)";
- break;
- case -2: /* incomplete */
- errstr = NULL;
- break;
- default: /* complete, with garbage on tail; should disable keepalive */
- client->_can_keepalive = 0;
- /* fallthru */
- case 0: /* complete */
- errstr = h2o_http1client_error_is_eos;
- break;
- }
- inbuf->size -= sock->bytes_read - newsz;
- cb_ret = client->_cb.on_body(&client->super, errstr);
- if (errstr != NULL) {
- close_client(client);
- return;
- } else if (cb_ret != 0) {
- client->_can_keepalive = 0;
- close_client(client);
- return;
- }
- }
-
- h2o_timeout_link(client->super.ctx->loop, client->super.ctx->io_timeout, &client->_timeout);
-}
-
-static void on_error_before_head(struct st_h2o_http1client_private_t *client, const char *errstr)
-{
- assert(!client->_can_keepalive);
- client->_cb.on_head(&client->super, errstr, 0, 0, h2o_iovec_init(NULL, 0), NULL, 0, 0);
- close_client(client);
-}
-
-static void on_head(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1client_private_t *client = sock->data;
- int minor_version, http_status, rlen, is_eos;
- const char *msg;
-#define MAX_HEADERS 100
- h2o_header_t *headers;
- h2o_iovec_t *header_names;
- size_t msg_len, num_headers, i;
- h2o_socket_cb reader;
- h2o_mem_pool_t pool;
-
- h2o_timeout_unlink(&client->_timeout);
-
- if (err != NULL) {
- on_error_before_head(client, "I/O error (head)");
- return;
- }
-
- h2o_mem_init_pool(&pool);
-
- headers = h2o_mem_alloc_pool(&pool, sizeof(*headers) * MAX_HEADERS);
- header_names = h2o_mem_alloc_pool(&pool, sizeof(*header_names) * MAX_HEADERS);
-
- /* continue parsing the responses until we see a final one */
- while (1) {
- /* parse response */
- struct phr_header src_headers[MAX_HEADERS];
- num_headers = MAX_HEADERS;
- rlen = phr_parse_response(sock->input->bytes, sock->input->size, &minor_version, &http_status, &msg, &msg_len, src_headers,
- &num_headers, 0);
- switch (rlen) {
- case -1: /* error */
- on_error_before_head(client, "failed to parse the response");
- goto Exit;
- case -2: /* incomplete */
- h2o_timeout_link(client->super.ctx->loop, client->super.ctx->io_timeout, &client->_timeout);
- goto Exit;
- }
- /* fill-in the headers */
- for (i = 0; i != num_headers; ++i) {
- const h2o_token_t *token;
- char *orig_name = h2o_strdup(&pool, src_headers[i].name, src_headers[i].name_len).base;
- h2o_strtolower((char *)src_headers[i].name, src_headers[i].name_len);
- token = h2o_lookup_token(src_headers[i].name, src_headers[i].name_len);
- if (token != NULL) {
- headers[i].name = (h2o_iovec_t *)&token->buf;
- } else {
- header_names[i] = h2o_iovec_init(src_headers[i].name, src_headers[i].name_len);
- headers[i].name = &header_names[i];
- }
- headers[i].value = h2o_iovec_init(src_headers[i].value, src_headers[i].value_len);
- headers[i].orig_name = orig_name;
- }
-
- if (!(100 <= http_status && http_status <= 199 && http_status != 101))
- break;
-
- if (client->super.informational_cb != NULL &&
- client->super.informational_cb(&client->super, minor_version, http_status, h2o_iovec_init(msg, msg_len), headers,
- num_headers) != 0) {
- close_client(client);
- goto Exit;
- }
- h2o_buffer_consume(&client->super.sock->input, rlen);
- if (client->super.sock->input->size == 0) {
- h2o_timeout_link(client->super.ctx->loop, client->super.ctx->io_timeout, &client->_timeout);
- goto Exit;
- }
- }
-
- /* parse the headers */
- reader = on_body_until_close;
- client->_can_keepalive = minor_version >= 1;
- for (i = 0; i != num_headers; ++i) {
- if (headers[i].name == &H2O_TOKEN_CONNECTION->buf) {
- if (h2o_contains_token(headers[i].value.base, headers[i].value.len, H2O_STRLIT("keep-alive"), ',')) {
- client->_can_keepalive = 1;
- } else {
- client->_can_keepalive = 0;
- }
- } else if (headers[i].name == &H2O_TOKEN_TRANSFER_ENCODING->buf) {
- if (h2o_memis(headers[i].value.base, headers[i].value.len, H2O_STRLIT("chunked"))) {
- /* precond: _body_decoder.chunked is zero-filled */
- client->_body_decoder.chunked.decoder.consume_trailer = 1;
- reader = on_body_chunked;
- } else if (h2o_memis(headers[i].value.base, headers[i].value.len, H2O_STRLIT("identity"))) {
- /* continue */
- } else {
- on_error_before_head(client, "unexpected type of transfer-encoding");
- goto Exit;
- }
- } else if (headers[i].name == &H2O_TOKEN_CONTENT_LENGTH->buf) {
- if ((client->_body_decoder.content_length.bytesleft = h2o_strtosize(headers[i].value.base, headers[i].value.len)) ==
- SIZE_MAX) {
- on_error_before_head(client, "invalid content-length");
- goto Exit;
- }
- if (reader != on_body_chunked)
- reader = on_body_content_length;
- }
- }
-
- /* RFC 2616 4.4 */
- if (client->_method_is_head || http_status == 101 || http_status == 204 || http_status == 304) {
- is_eos = 1;
- } else {
- is_eos = 0;
- /* close the connection if impossible to determine the end of the response (RFC 7230 3.3.3) */
- if (reader == on_body_until_close)
- client->_can_keepalive = 0;
- }
-
- /* call the callback. sock may be stealed and stealed sock need rlen.*/
- client->_cb.on_body = client->_cb.on_head(&client->super, is_eos ? h2o_http1client_error_is_eos : NULL, minor_version,
- http_status, h2o_iovec_init(msg, msg_len), headers, num_headers, rlen);
-
- if (is_eos) {
- close_client(client);
- goto Exit;
- } else if (client->_cb.on_body == NULL) {
- client->_can_keepalive = 0;
- close_client(client);
- goto Exit;
- }
-
- h2o_buffer_consume(&client->super.sock->input, rlen);
- client->super.sock->bytes_read = client->super.sock->input->size;
-
- client->_timeout.cb = on_body_timeout;
- h2o_socket_read_start(sock, reader);
- reader(client->super.sock, 0);
-
-Exit:
- h2o_mem_clear_pool(&pool);
-#undef MAX_HEADERS
-}
-
-static void on_head_timeout(h2o_timeout_entry_t *entry)
-{
- struct st_h2o_http1client_private_t *client = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1client_private_t, _timeout, entry);
- on_error_before_head(client, "I/O timeout");
-}
-
-static void on_send_request(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1client_private_t *client = sock->data;
-
- h2o_timeout_unlink(&client->_timeout);
-
- if (err != NULL) {
- on_error_before_head(client, "I/O error (send request)");
- return;
- }
-
- h2o_socket_read_start(client->super.sock, on_head);
- client->_timeout.cb = on_head_timeout;
- h2o_timeout_link(client->super.ctx->loop, client->super.ctx->io_timeout, &client->_timeout);
-}
-
-static void on_send_timeout(h2o_timeout_entry_t *entry)
-{
- struct st_h2o_http1client_private_t *client = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1client_private_t, _timeout, entry);
- on_error_before_head(client, "I/O timeout");
-}
-
-static void on_connect_error(struct st_h2o_http1client_private_t *client, const char *errstr)
-{
- assert(errstr != NULL);
- client->_cb.on_connect(&client->super, errstr, NULL, NULL, NULL);
- close_client(client);
-}
-
-static void on_connection_ready(struct st_h2o_http1client_private_t *client)
-{
- h2o_iovec_t *reqbufs;
- size_t reqbufcnt;
-
- if ((client->_cb.on_head = client->_cb.on_connect(&client->super, NULL, &reqbufs, &reqbufcnt, &client->_method_is_head)) ==
- NULL) {
- close_client(client);
- return;
- }
- h2o_socket_write(client->super.sock, reqbufs, reqbufcnt, on_send_request);
- /* TODO no need to set the timeout if all data has been written into TCP sendbuf */
- client->_timeout.cb = on_send_timeout;
- h2o_timeout_link(client->super.ctx->loop, client->super.ctx->io_timeout, &client->_timeout);
-}
-
-static void on_handshake_complete(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1client_private_t *client = sock->data;
-
- h2o_timeout_unlink(&client->_timeout);
-
- if (err == NULL) {
- /* success */
- } else if (err == h2o_socket_error_ssl_cert_name_mismatch &&
- (SSL_CTX_get_verify_mode(client->super.ctx->ssl_ctx) & SSL_VERIFY_PEER) == 0) {
- /* peer verification skipped */
- } else {
- on_connect_error(client, err);
- return;
- }
-
- on_connection_ready(client);
-}
-
-static void on_connect(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1client_private_t *client = sock->data;
-
- if (err != NULL) {
- h2o_timeout_unlink(&client->_timeout);
- on_connect_error(client, err);
- return;
- }
- if (client->super.ssl.server_name != NULL && client->super.sock->ssl == NULL) {
- h2o_socket_ssl_handshake(client->super.sock, client->super.ctx->ssl_ctx, client->super.ssl.server_name,
- on_handshake_complete);
- return;
- }
-
- h2o_timeout_unlink(&client->_timeout);
-
- on_connection_ready(client);
-}
-
-static void on_pool_connect(h2o_socket_t *sock, const char *errstr, void *data)
-{
- struct st_h2o_http1client_private_t *client = data;
-
- client->super.sockpool.connect_req = NULL;
-
- if (sock == NULL) {
- assert(errstr != NULL);
- on_connect_error(client, errstr);
- return;
- }
-
- client->super.sock = sock;
- sock->data = client;
- on_connect(sock, NULL);
-}
-
-static void on_connect_timeout(h2o_timeout_entry_t *entry)
-{
- struct st_h2o_http1client_private_t *client = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1client_private_t, _timeout, entry);
- on_connect_error(client, "connection timeout");
-}
-
-static void start_connect(struct st_h2o_http1client_private_t *client, struct sockaddr *addr, socklen_t addrlen)
-{
- if ((client->super.sock = h2o_socket_connect(client->super.ctx->loop, addr, addrlen, on_connect)) == NULL) {
- on_connect_error(client, "socket create error");
- return;
- }
- client->super.sock->data = client;
-}
-
-static void on_getaddr(h2o_hostinfo_getaddr_req_t *getaddr_req, const char *errstr, struct addrinfo *res, void *_client)
-{
- struct st_h2o_http1client_private_t *client = _client;
-
- assert(getaddr_req == client->_getaddr_req);
- client->_getaddr_req = NULL;
-
- if (errstr != NULL) {
- on_connect_error(client, errstr);
- return;
- }
-
- /* start connecting */
- struct addrinfo *selected = h2o_hostinfo_select_one(res);
- start_connect(client, selected->ai_addr, selected->ai_addrlen);
-}
-
-static struct st_h2o_http1client_private_t *create_client(h2o_http1client_t **_client, void *data, h2o_http1client_ctx_t *ctx,
- h2o_iovec_t ssl_server_name, h2o_http1client_connect_cb cb)
-{
- struct st_h2o_http1client_private_t *client = h2o_mem_alloc(sizeof(*client));
-
- *client = (struct st_h2o_http1client_private_t){{ctx}};
- if (ssl_server_name.base != NULL)
- client->super.ssl.server_name = h2o_strdup(NULL, ssl_server_name.base, ssl_server_name.len).base;
- client->super.data = data;
- client->_cb.on_connect = cb;
- /* caller needs to setup _cb, timeout.cb, sock, and sock->data */
-
- if (_client != NULL)
- *_client = &client->super;
- return client;
-}
-
-const char *const h2o_http1client_error_is_eos = "end of stream";
-
-void h2o_http1client_connect(h2o_http1client_t **_client, void *data, h2o_http1client_ctx_t *ctx, h2o_iovec_t host, uint16_t port,
- int is_ssl, h2o_http1client_connect_cb cb)
-{
- struct st_h2o_http1client_private_t *client;
- char serv[sizeof("65536")];
-
- /* setup */
- client = create_client(_client, data, ctx, is_ssl ? host : h2o_iovec_init(NULL, 0), cb);
- client->_timeout.cb = on_connect_timeout;
- h2o_timeout_link(ctx->loop, ctx->io_timeout, &client->_timeout);
-
- { /* directly call connect(2) if `host` is an IP address */
- struct sockaddr_in sin;
- memset(&sin, 0, sizeof(sin));
- if (h2o_hostinfo_aton(host, &sin.sin_addr) == 0) {
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- start_connect(client, (void *)&sin, sizeof(sin));
- return;
- }
- }
- { /* directly call connect(2) if `host` refers to an UNIX-domain socket */
- struct sockaddr_un sa;
- const char *to_sa_err;
- if ((to_sa_err = h2o_url_host_to_sun(host, &sa)) != h2o_url_host_to_sun_err_is_not_unix_socket) {
- if (to_sa_err != NULL) {
- on_connect_error(client, to_sa_err);
- return;
- }
- start_connect(client, (void *)&sa, sizeof(sa));
- return;
- }
- }
- /* resolve destination and then connect */
- client->_getaddr_req =
- h2o_hostinfo_getaddr(ctx->getaddr_receiver, host, h2o_iovec_init(serv, sprintf(serv, "%u", (unsigned)port)), AF_UNSPEC,
- SOCK_STREAM, IPPROTO_TCP, AI_ADDRCONFIG | AI_NUMERICSERV, on_getaddr, client);
-}
-
-void h2o_http1client_connect_with_pool(h2o_http1client_t **_client, void *data, h2o_http1client_ctx_t *ctx,
- h2o_socketpool_t *sockpool, h2o_http1client_connect_cb cb)
-{
- struct st_h2o_http1client_private_t *client =
- create_client(_client, data, ctx, sockpool->is_ssl ? sockpool->peer.host : h2o_iovec_init(NULL, 0), cb);
- client->super.sockpool.pool = sockpool;
- client->_timeout.cb = on_connect_timeout;
- h2o_timeout_link(ctx->loop, ctx->io_timeout, &client->_timeout);
- h2o_socketpool_connect(&client->super.sockpool.connect_req, sockpool, ctx->loop, ctx->getaddr_receiver, on_pool_connect,
- client);
-}
-
-void h2o_http1client_cancel(h2o_http1client_t *_client)
-{
- struct st_h2o_http1client_private_t *client = (void *)_client;
- client->_can_keepalive = 0;
- close_client(client);
-}
-
-h2o_socket_t *h2o_http1client_steal_socket(h2o_http1client_t *_client)
-{
- struct st_h2o_http1client_private_t *client = (void *)_client;
- h2o_socket_t *sock = client->super.sock;
- h2o_socket_read_stop(sock);
- client->super.sock = NULL;
- return sock;
-}
diff --git a/web/server/h2o/libh2o/lib/common/memcached.c b/web/server/h2o/libh2o/lib/common/memcached.c
deleted file mode 100644
index 752ea2fcb..000000000
--- a/web/server/h2o/libh2o/lib/common/memcached.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <errno.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include "yrmcds.h"
-#include "h2o/linklist.h"
-#include "h2o/memcached.h"
-#include "h2o/rand.h"
-#include "h2o/string_.h"
-
-struct st_h2o_memcached_context_t {
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- h2o_linklist_t pending;
- size_t num_threads_connected;
- char *host;
- uint16_t port;
- int text_protocol;
- h2o_iovec_t prefix;
-};
-
-struct st_h2o_memcached_conn_t {
- h2o_memcached_context_t *ctx;
- yrmcds yrmcds;
- pthread_mutex_t mutex;
- h2o_linklist_t inflight;
- int writer_exit_requested;
-};
-
-enum en_h2o_memcached_req_type_t { REQ_TYPE_GET, REQ_TYPE_SET, REQ_TYPE_DELETE };
-
-struct st_h2o_memcached_req_t {
- enum en_h2o_memcached_req_type_t type;
- h2o_linklist_t pending;
- h2o_linklist_t inflight;
- union {
- struct {
- h2o_multithread_receiver_t *receiver;
- h2o_multithread_message_t message;
- h2o_memcached_get_cb cb;
- void *cb_data;
- int value_is_encoded;
- h2o_iovec_t value;
- uint32_t serial;
- } get;
- struct {
- h2o_iovec_t value;
- uint32_t expiration;
- } set;
- } data;
- struct {
- size_t len;
- char base[1];
- } key;
-};
-
-static h2o_memcached_req_t *create_req(h2o_memcached_context_t *ctx, enum en_h2o_memcached_req_type_t type, h2o_iovec_t key,
- int encode_key)
-{
- h2o_memcached_req_t *req = h2o_mem_alloc(offsetof(h2o_memcached_req_t, key.base) + ctx->prefix.len +
- (encode_key ? (key.len + 2) / 3 * 4 + 1 : key.len));
- req->type = type;
- req->pending = (h2o_linklist_t){NULL};
- req->inflight = (h2o_linklist_t){NULL};
- memset(&req->data, 0, sizeof(req->data));
- if (ctx->prefix.len != 0)
- memcpy(req->key.base, ctx->prefix.base, ctx->prefix.len);
- req->key.len = ctx->prefix.len;
- if (encode_key) {
- req->key.len += h2o_base64_encode(req->key.base + req->key.len, key.base, key.len, 1);
- } else {
- memcpy(req->key.base + req->key.len, key.base, key.len);
- req->key.len += key.len;
- }
- return req;
-}
-
-static void free_req(h2o_memcached_req_t *req)
-{
- assert(!h2o_linklist_is_linked(&req->pending));
- switch (req->type) {
- case REQ_TYPE_GET:
- assert(!h2o_linklist_is_linked(&req->data.get.message.link));
- h2o_mem_set_secure(req->data.get.value.base, 0, req->data.get.value.len);
- free(req->data.get.value.base);
- break;
- case REQ_TYPE_SET:
- h2o_mem_set_secure(req->data.set.value.base, 0, req->data.set.value.len);
- free(req->data.set.value.base);
- break;
- case REQ_TYPE_DELETE:
- break;
- default:
- assert(!"FIXME");
- break;
- }
- free(req);
-}
-
-static void discard_req(h2o_memcached_req_t *req)
-{
- switch (req->type) {
- case REQ_TYPE_GET:
- h2o_multithread_send_message(req->data.get.receiver, &req->data.get.message);
- break;
- default:
- free_req(req);
- break;
- }
-}
-
-static h2o_memcached_req_t *pop_inflight(struct st_h2o_memcached_conn_t *conn, uint32_t serial)
-{
- h2o_memcached_req_t *req;
-
- pthread_mutex_lock(&conn->mutex);
-
- if (conn->yrmcds.text_mode) {
- /* in text mode, responses are returned in order (and we may receive responses for commands other than GET) */
- if (!h2o_linklist_is_empty(&conn->inflight)) {
- req = H2O_STRUCT_FROM_MEMBER(h2o_memcached_req_t, inflight, conn->inflight.next);
- assert(req->type == REQ_TYPE_GET);
- if (req->data.get.serial == serial)
- goto Found;
- }
- } else {
- /* in binary mode, responses are received out-of-order (and we would only recieve responses for GET) */
- h2o_linklist_t *node;
- for (node = conn->inflight.next; node != &conn->inflight; node = node->next) {
- req = H2O_STRUCT_FROM_MEMBER(h2o_memcached_req_t, inflight, node);
- assert(req->type == REQ_TYPE_GET);
- if (req->data.get.serial == serial)
- goto Found;
- }
- }
-
- /* not found */
- pthread_mutex_unlock(&conn->mutex);
- return NULL;
-
-Found:
- h2o_linklist_unlink(&req->inflight);
- pthread_mutex_unlock(&conn->mutex);
- return req;
-}
-
-static void *writer_main(void *_conn)
-{
- struct st_h2o_memcached_conn_t *conn = _conn;
- yrmcds_error err;
-
- pthread_mutex_lock(&conn->ctx->mutex);
-
- while (!__sync_add_and_fetch(&conn->writer_exit_requested, 0)) {
- while (!h2o_linklist_is_empty(&conn->ctx->pending)) {
- h2o_memcached_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_memcached_req_t, pending, conn->ctx->pending.next);
- h2o_linklist_unlink(&req->pending);
- pthread_mutex_unlock(&conn->ctx->mutex);
-
- switch (req->type) {
- case REQ_TYPE_GET:
- pthread_mutex_lock(&conn->mutex);
- h2o_linklist_insert(&conn->inflight, &req->inflight);
- pthread_mutex_unlock(&conn->mutex);
- if ((err = yrmcds_get(&conn->yrmcds, req->key.base, req->key.len, 0, &req->data.get.serial)) != YRMCDS_OK)
- goto Error;
- break;
- case REQ_TYPE_SET:
- err = yrmcds_set(&conn->yrmcds, req->key.base, req->key.len, req->data.set.value.base, req->data.set.value.len, 0,
- req->data.set.expiration, 0, !conn->yrmcds.text_mode, NULL);
- discard_req(req);
- if (err != YRMCDS_OK)
- goto Error;
- break;
- case REQ_TYPE_DELETE:
- err = yrmcds_remove(&conn->yrmcds, req->key.base, req->key.len, !conn->yrmcds.text_mode, NULL);
- discard_req(req);
- if (err != YRMCDS_OK)
- goto Error;
- break;
- default:
- fprintf(stderr, "[lib/common/memcached.c] unknown type:%d\n", (int)req->type);
- err = YRMCDS_NOT_IMPLEMENTED;
- goto Error;
- }
-
- pthread_mutex_lock(&conn->ctx->mutex);
- }
- pthread_cond_wait(&conn->ctx->cond, &conn->ctx->mutex);
- }
-
- pthread_mutex_unlock(&conn->ctx->mutex);
- return NULL;
-
-Error:
- fprintf(stderr, "[lib/common/memcached.c] failed to send request; %s\n", yrmcds_strerror(err));
- /* doc says the call can be used to interrupt yrmcds_recv */
- yrmcds_shutdown(&conn->yrmcds);
-
- return NULL;
-}
-
-static void connect_to_server(h2o_memcached_context_t *ctx, yrmcds *yrmcds)
-{
- size_t failcnt;
- yrmcds_error err;
-
- for (failcnt = 0; (err = yrmcds_connect(yrmcds, ctx->host, ctx->port)) != YRMCDS_OK; ++failcnt) {
- if (failcnt == 0) {
- fprintf(stderr, "[lib/common/memcached.c] failed to connect to memcached at %s:%" PRIu16 ", %s\n", ctx->host, ctx->port,
- yrmcds_strerror(err));
- }
- ++failcnt;
- usleep(2000000 + h2o_rand() % 3000000); /* sleep 2 to 5 seconds */
- }
- /* connected */
- if (ctx->text_protocol)
- yrmcds_text_mode(yrmcds);
- fprintf(stderr, "[lib/common/memcached.c] connected to memcached at %s:%" PRIu16 "\n", ctx->host, ctx->port);
-}
-
-static void reader_main(h2o_memcached_context_t *ctx)
-{
- struct st_h2o_memcached_conn_t conn = {ctx, {0}, PTHREAD_MUTEX_INITIALIZER, {&conn.inflight, &conn.inflight}, 0};
- pthread_t writer_thread;
- yrmcds_response resp;
- yrmcds_error err;
-
- /* connect to server and start the writer thread */
- connect_to_server(conn.ctx, &conn.yrmcds);
- if (pthread_create(&writer_thread, NULL, writer_main, &conn) != 0) {
- perror("pthread_create");
- abort();
- }
-
- pthread_mutex_lock(&conn.ctx->mutex);
- ++conn.ctx->num_threads_connected;
- pthread_mutex_unlock(&conn.ctx->mutex);
-
- /* receive data until an error occurs */
- while (1) {
- if ((err = yrmcds_recv(&conn.yrmcds, &resp)) != YRMCDS_OK) {
- fprintf(stderr, "[lib/common/memcached.c] yrmcds_recv:%s\n", yrmcds_strerror(err));
- break;
- }
- h2o_memcached_req_t *req = pop_inflight(&conn, resp.serial);
- if (req == NULL) {
- if (conn.yrmcds.text_mode)
- continue;
- fprintf(stderr, "[lib/common/memcached.c] received unexpected serial\n");
- break;
- }
- if (resp.status == YRMCDS_STATUS_OK) {
- req->data.get.value = h2o_iovec_init(h2o_mem_alloc(resp.data_len), resp.data_len);
- memcpy(req->data.get.value.base, resp.data, resp.data_len);
- h2o_mem_set_secure((void *)resp.data, 0, resp.data_len);
- }
- h2o_multithread_send_message(req->data.get.receiver, &req->data.get.message);
- }
-
- /* send error to all the reqs in-flight */
- pthread_mutex_lock(&conn.mutex);
- while (!h2o_linklist_is_empty(&conn.inflight)) {
- h2o_memcached_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_memcached_req_t, inflight, conn.inflight.next);
- h2o_linklist_unlink(&req->inflight);
- assert(req->type == REQ_TYPE_GET);
- h2o_multithread_send_message(req->data.get.receiver, &req->data.get.message);
- }
- pthread_mutex_unlock(&conn.mutex);
-
- /* stop the writer thread */
- __sync_add_and_fetch(&conn.writer_exit_requested, 1);
- pthread_mutex_lock(&conn.ctx->mutex);
- pthread_cond_broadcast(&conn.ctx->cond);
- pthread_mutex_unlock(&conn.ctx->mutex);
- pthread_join(writer_thread, NULL);
-
- /* decrement num_threads_connected, and discard all the pending requests if no connections are alive */
- pthread_mutex_lock(&conn.ctx->mutex);
- if (--conn.ctx->num_threads_connected == 0) {
- while (!h2o_linklist_is_empty(&conn.ctx->pending)) {
- h2o_memcached_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_memcached_req_t, pending, conn.ctx->pending.next);
- h2o_linklist_unlink(&req->pending);
- discard_req(req);
- }
- }
- pthread_mutex_unlock(&conn.ctx->mutex);
-
- /* close the connection */
- yrmcds_close(&conn.yrmcds);
-}
-
-static void *thread_main(void *_ctx)
-{
- h2o_memcached_context_t *ctx = _ctx;
-
- while (1)
- reader_main(ctx);
- return NULL;
-}
-
-static void dispatch(h2o_memcached_context_t *ctx, h2o_memcached_req_t *req)
-{
- pthread_mutex_lock(&ctx->mutex);
-
- if (ctx->num_threads_connected != 0) {
- h2o_linklist_insert(&ctx->pending, &req->pending);
- pthread_cond_signal(&ctx->cond);
- } else {
- discard_req(req);
- }
-
- pthread_mutex_unlock(&ctx->mutex);
-}
-
-void h2o_memcached_receiver(h2o_multithread_receiver_t *receiver, h2o_linklist_t *messages)
-{
- while (!h2o_linklist_is_empty(messages)) {
- h2o_memcached_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_memcached_req_t, data.get.message.link, messages->next);
- h2o_linklist_unlink(&req->data.get.message.link);
- assert(req->type == REQ_TYPE_GET);
- if (req->data.get.cb != NULL) {
- if (req->data.get.value_is_encoded && req->data.get.value.len != 0) {
- h2o_iovec_t decoded = h2o_decode_base64url(NULL, req->data.get.value.base, req->data.get.value.len);
- h2o_mem_set_secure(req->data.get.value.base, 0, req->data.get.value.len);
- free(req->data.get.value.base);
- req->data.get.value = decoded;
- }
- req->data.get.cb(req->data.get.value, req->data.get.cb_data);
- }
- free_req(req);
- }
-}
-
-h2o_memcached_req_t *h2o_memcached_get(h2o_memcached_context_t *ctx, h2o_multithread_receiver_t *receiver, h2o_iovec_t key,
- h2o_memcached_get_cb cb, void *cb_data, int flags)
-{
- h2o_memcached_req_t *req = create_req(ctx, REQ_TYPE_GET, key, (flags & H2O_MEMCACHED_ENCODE_KEY) != 0);
- req->data.get.receiver = receiver;
- req->data.get.cb = cb;
- req->data.get.cb_data = cb_data;
- req->data.get.value_is_encoded = (flags & H2O_MEMCACHED_ENCODE_VALUE) != 0;
- dispatch(ctx, req);
- return req;
-}
-
-void h2o_memcached_cancel_get(h2o_memcached_context_t *ctx, h2o_memcached_req_t *req)
-{
- int do_free = 0;
-
- pthread_mutex_lock(&ctx->mutex);
- req->data.get.cb = NULL;
- if (h2o_linklist_is_linked(&req->pending)) {
- h2o_linklist_unlink(&req->pending);
- do_free = 1;
- }
- pthread_mutex_unlock(&ctx->mutex);
-
- if (do_free)
- free_req(req);
-}
-
-void h2o_memcached_set(h2o_memcached_context_t *ctx, h2o_iovec_t key, h2o_iovec_t value, uint32_t expiration, int flags)
-{
- h2o_memcached_req_t *req = create_req(ctx, REQ_TYPE_SET, key, (flags & H2O_MEMCACHED_ENCODE_KEY) != 0);
- if ((flags & H2O_MEMCACHED_ENCODE_VALUE) != 0) {
- req->data.set.value.base = h2o_mem_alloc((value.len + 2) / 3 * 4 + 1);
- req->data.set.value.len = h2o_base64_encode(req->data.set.value.base, value.base, value.len, 1);
- } else {
- req->data.set.value = h2o_iovec_init(h2o_mem_alloc(value.len), value.len);
- memcpy(req->data.set.value.base, value.base, value.len);
- }
- req->data.set.expiration = expiration;
- dispatch(ctx, req);
-}
-
-void h2o_memcached_delete(h2o_memcached_context_t *ctx, h2o_iovec_t key, int flags)
-{
- h2o_memcached_req_t *req = create_req(ctx, REQ_TYPE_DELETE, key, (flags & H2O_MEMCACHED_ENCODE_KEY) != 0);
- dispatch(ctx, req);
-}
-
-h2o_memcached_context_t *h2o_memcached_create_context(const char *host, uint16_t port, int text_protocol, size_t num_threads,
- const char *prefix)
-{
- h2o_memcached_context_t *ctx = h2o_mem_alloc(sizeof(*ctx));
-
- pthread_mutex_init(&ctx->mutex, NULL);
- pthread_cond_init(&ctx->cond, NULL);
- h2o_linklist_init_anchor(&ctx->pending);
- ctx->num_threads_connected = 0;
- ctx->host = h2o_strdup(NULL, host, SIZE_MAX).base;
- ctx->port = port;
- ctx->text_protocol = text_protocol;
- ctx->prefix = h2o_strdup(NULL, prefix, SIZE_MAX);
-
- { /* start the threads */
- pthread_t tid;
- pthread_attr_t attr;
- size_t i;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, 1);
- for (i = 0; i != num_threads; ++i)
- h2o_multithread_create_thread(&tid, &attr, thread_main, ctx);
- pthread_attr_destroy(&attr);
- }
-
- return ctx;
-}
diff --git a/web/server/h2o/libh2o/lib/common/memory.c b/web/server/h2o/libh2o/lib/common/memory.c
deleted file mode 100644
index ba9f2dba2..000000000
--- a/web/server/h2o/libh2o/lib/common/memory.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * 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 <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include "h2o/memory.h"
-
-#if defined(__linux__)
-#define USE_POSIX_FALLOCATE 1
-#elif __FreeBSD__ >= 9
-#define USE_POSIX_FALLOCATE 1
-#elif __NetBSD__ >= 7
-#define USE_POSIX_FALLOCATE 1
-#else
-#define USE_POSIX_FALLOCATE 0
-#endif
-
-struct st_h2o_mem_recycle_chunk_t {
- struct st_h2o_mem_recycle_chunk_t *next;
-};
-
-struct st_h2o_mem_pool_chunk_t {
- struct st_h2o_mem_pool_chunk_t *next;
- size_t _dummy; /* align to 2*sizeof(void*) */
- char bytes[4096 - sizeof(void *) * 2];
-};
-
-struct st_h2o_mem_pool_direct_t {
- struct st_h2o_mem_pool_direct_t *next;
- size_t _dummy; /* align to 2*sizeof(void*) */
- char bytes[1];
-};
-
-struct st_h2o_mem_pool_shared_ref_t {
- struct st_h2o_mem_pool_shared_ref_t *next;
- struct st_h2o_mem_pool_shared_entry_t *entry;
-};
-
-void *(*h2o_mem__set_secure)(void *, int, size_t) = memset;
-
-static __thread h2o_mem_recycle_t mempool_allocator = {16};
-
-void h2o__fatal(const char *msg)
-{
- fprintf(stderr, "fatal:%s\n", msg);
- abort();
-}
-
-void *h2o_mem_alloc_recycle(h2o_mem_recycle_t *allocator, size_t sz)
-{
- struct st_h2o_mem_recycle_chunk_t *chunk;
- if (allocator->cnt == 0)
- return h2o_mem_alloc(sz);
- /* detach and return the pooled pointer */
- chunk = allocator->_link;
- assert(chunk != NULL);
- allocator->_link = chunk->next;
- --allocator->cnt;
- return chunk;
-}
-
-void h2o_mem_free_recycle(h2o_mem_recycle_t *allocator, void *p)
-{
- struct st_h2o_mem_recycle_chunk_t *chunk;
- if (allocator->cnt == allocator->max) {
- free(p);
- return;
- }
- /* register the pointer to the pool */
- chunk = p;
- chunk->next = allocator->_link;
- allocator->_link = chunk;
- ++allocator->cnt;
-}
-
-void h2o_mem_init_pool(h2o_mem_pool_t *pool)
-{
- pool->chunks = NULL;
- pool->chunk_offset = sizeof(pool->chunks->bytes);
- pool->directs = NULL;
- pool->shared_refs = NULL;
-}
-
-void h2o_mem_clear_pool(h2o_mem_pool_t *pool)
-{
- /* release the refcounted chunks */
- if (pool->shared_refs != NULL) {
- struct st_h2o_mem_pool_shared_ref_t *ref = pool->shared_refs;
- do {
- h2o_mem_release_shared(ref->entry->bytes);
- } while ((ref = ref->next) != NULL);
- pool->shared_refs = NULL;
- }
- /* release the direct chunks */
- if (pool->directs != NULL) {
- struct st_h2o_mem_pool_direct_t *direct = pool->directs, *next;
- do {
- next = direct->next;
- free(direct);
- } while ((direct = next) != NULL);
- pool->directs = NULL;
- }
- /* free chunks, and reset the first chunk */
- while (pool->chunks != NULL) {
- struct st_h2o_mem_pool_chunk_t *next = pool->chunks->next;
- h2o_mem_free_recycle(&mempool_allocator, pool->chunks);
- pool->chunks = next;
- }
- pool->chunk_offset = sizeof(pool->chunks->bytes);
-}
-
-void *h2o_mem_alloc_pool(h2o_mem_pool_t *pool, size_t sz)
-{
- void *ret;
-
- if (sz >= sizeof(pool->chunks->bytes) / 4) {
- /* allocate large requests directly */
- struct st_h2o_mem_pool_direct_t *newp = h2o_mem_alloc(offsetof(struct st_h2o_mem_pool_direct_t, bytes) + sz);
- newp->next = pool->directs;
- pool->directs = newp;
- return newp->bytes;
- }
-
- /* return a valid pointer even for 0 sized allocs */
- if (sz == 0)
- sz = 1;
-
- /* 16-bytes rounding */
- sz = (sz + 15) & ~15;
- if (sizeof(pool->chunks->bytes) - pool->chunk_offset < sz) {
- /* allocate new chunk */
- struct st_h2o_mem_pool_chunk_t *newp = h2o_mem_alloc_recycle(&mempool_allocator, sizeof(*newp));
- newp->next = pool->chunks;
- pool->chunks = newp;
- pool->chunk_offset = 0;
- }
-
- ret = pool->chunks->bytes + pool->chunk_offset;
- pool->chunk_offset += sz;
- return ret;
-}
-
-static void link_shared(h2o_mem_pool_t *pool, struct st_h2o_mem_pool_shared_entry_t *entry)
-{
- struct st_h2o_mem_pool_shared_ref_t *ref = h2o_mem_alloc_pool(pool, sizeof(struct st_h2o_mem_pool_shared_ref_t));
- ref->entry = entry;
- ref->next = pool->shared_refs;
- pool->shared_refs = ref;
-}
-
-void *h2o_mem_alloc_shared(h2o_mem_pool_t *pool, size_t sz, void (*dispose)(void *))
-{
- struct st_h2o_mem_pool_shared_entry_t *entry = h2o_mem_alloc(offsetof(struct st_h2o_mem_pool_shared_entry_t, bytes) + sz);
- entry->refcnt = 1;
- entry->dispose = dispose;
- if (pool != NULL)
- link_shared(pool, entry);
- return entry->bytes;
-}
-
-void h2o_mem_link_shared(h2o_mem_pool_t *pool, void *p)
-{
- h2o_mem_addref_shared(p);
- link_shared(pool, H2O_STRUCT_FROM_MEMBER(struct st_h2o_mem_pool_shared_entry_t, bytes, p));
-}
-
-static size_t topagesize(size_t capacity)
-{
- size_t pagesize = getpagesize();
- return (offsetof(h2o_buffer_t, _buf) + capacity + pagesize - 1) / pagesize * pagesize;
-}
-
-void h2o_buffer__do_free(h2o_buffer_t *buffer)
-{
- /* caller should assert that the buffer is not part of the prototype */
- if (buffer->capacity == buffer->_prototype->_initial_buf.capacity) {
- h2o_mem_free_recycle(&buffer->_prototype->allocator, buffer);
- } else if (buffer->_fd != -1) {
- close(buffer->_fd);
- munmap((void *)buffer, topagesize(buffer->capacity));
- } else {
- free(buffer);
- }
-}
-
-h2o_iovec_t h2o_buffer_reserve(h2o_buffer_t **_inbuf, size_t min_guarantee)
-{
- h2o_buffer_t *inbuf = *_inbuf;
- h2o_iovec_t ret;
-
- if (inbuf->bytes == NULL) {
- h2o_buffer_prototype_t *prototype = H2O_STRUCT_FROM_MEMBER(h2o_buffer_prototype_t, _initial_buf, inbuf);
- if (min_guarantee <= prototype->_initial_buf.capacity) {
- min_guarantee = prototype->_initial_buf.capacity;
- inbuf = h2o_mem_alloc_recycle(&prototype->allocator, offsetof(h2o_buffer_t, _buf) + min_guarantee);
- } else {
- inbuf = h2o_mem_alloc(offsetof(h2o_buffer_t, _buf) + min_guarantee);
- }
- *_inbuf = inbuf;
- inbuf->size = 0;
- inbuf->bytes = inbuf->_buf;
- inbuf->capacity = min_guarantee;
- inbuf->_prototype = prototype;
- inbuf->_fd = -1;
- } else {
- if (min_guarantee <= inbuf->capacity - inbuf->size - (inbuf->bytes - inbuf->_buf)) {
- /* ok */
- } else if ((inbuf->size + min_guarantee) * 2 <= inbuf->capacity) {
- /* the capacity should be less than or equal to 2 times of: size + guarantee */
- memmove(inbuf->_buf, inbuf->bytes, inbuf->size);
- inbuf->bytes = inbuf->_buf;
- } else {
- size_t new_capacity = inbuf->capacity;
- do {
- new_capacity *= 2;
- } while (new_capacity - inbuf->size < min_guarantee);
- if (inbuf->_prototype->mmap_settings != NULL && inbuf->_prototype->mmap_settings->threshold <= new_capacity) {
- size_t new_allocsize = topagesize(new_capacity);
- int fd;
- h2o_buffer_t *newp;
- if (inbuf->_fd == -1) {
- char *tmpfn = alloca(strlen(inbuf->_prototype->mmap_settings->fn_template) + 1);
- strcpy(tmpfn, inbuf->_prototype->mmap_settings->fn_template);
- if ((fd = mkstemp(tmpfn)) == -1) {
- fprintf(stderr, "failed to create temporary file:%s:%s\n", tmpfn, strerror(errno));
- goto MapError;
- }
- unlink(tmpfn);
- } else {
- fd = inbuf->_fd;
- }
- int fallocate_ret;
-#if USE_POSIX_FALLOCATE
- fallocate_ret = posix_fallocate(fd, 0, new_allocsize);
-#else
- fallocate_ret = ftruncate(fd, new_allocsize);
-#endif
- if (fallocate_ret != 0) {
- perror("failed to resize temporary file");
- goto MapError;
- }
- if ((newp = (void *)mmap(NULL, new_allocsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
- perror("mmap failed");
- goto MapError;
- }
- if (inbuf->_fd == -1) {
- /* copy data (moving from malloc to mmap) */
- newp->size = inbuf->size;
- newp->bytes = newp->_buf;
- newp->capacity = new_capacity;
- newp->_prototype = inbuf->_prototype;
- newp->_fd = fd;
- memcpy(newp->_buf, inbuf->bytes, inbuf->size);
- h2o_buffer__do_free(inbuf);
- *_inbuf = inbuf = newp;
- } else {
- /* munmap */
- size_t offset = inbuf->bytes - inbuf->_buf;
- munmap((void *)inbuf, topagesize(inbuf->capacity));
- *_inbuf = inbuf = newp;
- inbuf->capacity = new_capacity;
- inbuf->bytes = newp->_buf + offset;
- }
- } else {
- h2o_buffer_t *newp = h2o_mem_alloc(offsetof(h2o_buffer_t, _buf) + new_capacity);
- newp->size = inbuf->size;
- newp->bytes = newp->_buf;
- newp->capacity = new_capacity;
- newp->_prototype = inbuf->_prototype;
- newp->_fd = -1;
- memcpy(newp->_buf, inbuf->bytes, inbuf->size);
- h2o_buffer__do_free(inbuf);
- *_inbuf = inbuf = newp;
- }
- }
- }
-
- ret.base = inbuf->bytes + inbuf->size;
- ret.len = inbuf->_buf + inbuf->capacity - ret.base;
-
- return ret;
-
-MapError:
- ret.base = NULL;
- ret.len = 0;
- return ret;
-}
-
-void h2o_buffer_consume(h2o_buffer_t **_inbuf, size_t delta)
-{
- h2o_buffer_t *inbuf = *_inbuf;
-
- if (delta != 0) {
- assert(inbuf->bytes != NULL);
- if (inbuf->size == delta) {
- *_inbuf = &inbuf->_prototype->_initial_buf;
- h2o_buffer__do_free(inbuf);
- } else {
- inbuf->size -= delta;
- inbuf->bytes += delta;
- }
- }
-}
-
-void h2o_buffer__dispose_linked(void *p)
-{
- h2o_buffer_t **buf = p;
- h2o_buffer_dispose(buf);
-}
-
-void h2o_vector__expand(h2o_mem_pool_t *pool, h2o_vector_t *vector, size_t element_size, size_t new_capacity)
-{
- void *new_entries;
- assert(vector->capacity < new_capacity);
- if (vector->capacity == 0)
- vector->capacity = 4;
- while (vector->capacity < new_capacity)
- vector->capacity *= 2;
- if (pool != NULL) {
- new_entries = h2o_mem_alloc_pool(pool, element_size * vector->capacity);
- h2o_memcpy(new_entries, vector->entries, element_size * vector->size);
- } else {
- new_entries = h2o_mem_realloc(vector->entries, element_size * vector->capacity);
- }
- vector->entries = new_entries;
-}
-
-void h2o_mem_swap(void *_x, void *_y, size_t len)
-{
- char *x = _x, *y = _y;
- char buf[256];
-
- while (len != 0) {
- size_t blocksz = len < sizeof(buf) ? len : sizeof(buf);
- memcpy(buf, x, blocksz);
- memcpy(x, y, blocksz);
- memcpy(y, buf, blocksz);
- len -= blocksz;
- x += blocksz;
- y += blocksz;
- }
-}
-
-void h2o_dump_memory(FILE *fp, const char *buf, size_t len)
-{
- size_t i, j;
-
- for (i = 0; i < len; i += 16) {
- fprintf(fp, "%08zx", i);
- for (j = 0; j != 16; ++j) {
- if (i + j < len)
- fprintf(fp, " %02x", (int)(unsigned char)buf[i + j]);
- else
- fprintf(fp, " ");
- }
- fprintf(fp, " ");
- for (j = 0; j != 16 && i + j < len; ++j) {
- int ch = buf[i + j];
- fputc(' ' <= ch && ch < 0x7f ? ch : '.', fp);
- }
- fprintf(fp, "\n");
- }
-}
-
-void h2o_append_to_null_terminated_list(void ***list, void *element)
-{
- size_t cnt;
-
- for (cnt = 0; (*list)[cnt] != NULL; ++cnt)
- ;
- *list = h2o_mem_realloc(*list, (cnt + 2) * sizeof(void *));
- (*list)[cnt++] = element;
- (*list)[cnt] = NULL;
-}
diff --git a/web/server/h2o/libh2o/lib/common/multithread.c b/web/server/h2o/libh2o/lib/common/multithread.c
deleted file mode 100644
index b4e8ba836..000000000
--- a/web/server/h2o/libh2o/lib/common/multithread.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (c) 2015-2016 DeNA Co., Ltd., Kazuho Oku, Tatsuhiko Kubo,
- * Chul-Woong Yang
- *
- * 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 <assert.h>
-#include <pthread.h>
-#include "cloexec.h"
-#include "h2o/multithread.h"
-
-struct st_h2o_multithread_queue_t {
-#if H2O_USE_LIBUV
- uv_async_t async;
-#else
- struct {
- int write;
- h2o_socket_t *read;
- } async;
-#endif
- pthread_mutex_t mutex;
- struct {
- h2o_linklist_t active;
- h2o_linklist_t inactive;
- } receivers;
-};
-
-static void queue_cb(h2o_multithread_queue_t *queue)
-{
- pthread_mutex_lock(&queue->mutex);
-
- while (!h2o_linklist_is_empty(&queue->receivers.active)) {
- h2o_multithread_receiver_t *receiver =
- H2O_STRUCT_FROM_MEMBER(h2o_multithread_receiver_t, _link, queue->receivers.active.next);
- /* detach all the messages from the receiver */
- h2o_linklist_t messages;
- h2o_linklist_init_anchor(&messages);
- h2o_linklist_insert_list(&messages, &receiver->_messages);
- /* relink the receiver to the inactive list */
- h2o_linklist_unlink(&receiver->_link);
- h2o_linklist_insert(&queue->receivers.inactive, &receiver->_link);
-
- /* dispatch the messages */
- pthread_mutex_unlock(&queue->mutex);
- receiver->cb(receiver, &messages);
- assert(h2o_linklist_is_empty(&messages));
- pthread_mutex_lock(&queue->mutex);
- }
-
- pthread_mutex_unlock(&queue->mutex);
-}
-
-#ifdef H2O_NO_64BIT_ATOMICS
-pthread_mutex_t h2o_conn_id_mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-#if H2O_USE_LIBUV
-#else
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-static void on_read(h2o_socket_t *sock, const char *err)
-{
- if (err != NULL) {
- fprintf(stderr, "pipe error\n");
- abort();
- }
-
- h2o_buffer_consume(&sock->input, sock->input->size);
- queue_cb(sock->data);
-}
-
-static void init_async(h2o_multithread_queue_t *queue, h2o_loop_t *loop)
-{
- int fds[2];
-
- if (cloexec_pipe(fds) != 0) {
- perror("pipe");
- abort();
- }
- fcntl(fds[1], F_SETFL, O_NONBLOCK);
- queue->async.write = fds[1];
- queue->async.read = h2o_evloop_socket_create(loop, fds[0], 0);
- queue->async.read->data = queue;
- h2o_socket_read_start(queue->async.read, on_read);
-}
-
-#endif
-
-h2o_multithread_queue_t *h2o_multithread_create_queue(h2o_loop_t *loop)
-{
- h2o_multithread_queue_t *queue = h2o_mem_alloc(sizeof(*queue));
- memset(queue, 0, sizeof(*queue));
-
-#if H2O_USE_LIBUV
- uv_async_init(loop, &queue->async, (uv_async_cb)queue_cb);
-#else
- init_async(queue, loop);
-#endif
- pthread_mutex_init(&queue->mutex, NULL);
- h2o_linklist_init_anchor(&queue->receivers.active);
- h2o_linklist_init_anchor(&queue->receivers.inactive);
-
- return queue;
-}
-
-void h2o_multithread_destroy_queue(h2o_multithread_queue_t *queue)
-{
- assert(h2o_linklist_is_empty(&queue->receivers.active));
- assert(h2o_linklist_is_empty(&queue->receivers.inactive));
-#if H2O_USE_LIBUV
- uv_close((uv_handle_t *)&queue->async, (uv_close_cb)free);
-#else
- h2o_socket_read_stop(queue->async.read);
- h2o_socket_close(queue->async.read);
- close(queue->async.write);
-#endif
- pthread_mutex_destroy(&queue->mutex);
-}
-
-void h2o_multithread_register_receiver(h2o_multithread_queue_t *queue, h2o_multithread_receiver_t *receiver,
- h2o_multithread_receiver_cb cb)
-{
- receiver->queue = queue;
- receiver->_link = (h2o_linklist_t){NULL};
- h2o_linklist_init_anchor(&receiver->_messages);
- receiver->cb = cb;
-
- pthread_mutex_lock(&queue->mutex);
- h2o_linklist_insert(&queue->receivers.inactive, &receiver->_link);
- pthread_mutex_unlock(&queue->mutex);
-}
-
-void h2o_multithread_unregister_receiver(h2o_multithread_queue_t *queue, h2o_multithread_receiver_t *receiver)
-{
- assert(queue == receiver->queue);
- assert(h2o_linklist_is_empty(&receiver->_messages));
- pthread_mutex_lock(&queue->mutex);
- h2o_linklist_unlink(&receiver->_link);
- pthread_mutex_unlock(&queue->mutex);
-}
-
-void h2o_multithread_send_message(h2o_multithread_receiver_t *receiver, h2o_multithread_message_t *message)
-{
- int do_send = 0;
-
- pthread_mutex_lock(&receiver->queue->mutex);
- if (message != NULL) {
- assert(!h2o_linklist_is_linked(&message->link));
- if (h2o_linklist_is_empty(&receiver->_messages)) {
- h2o_linklist_unlink(&receiver->_link);
- h2o_linklist_insert(&receiver->queue->receivers.active, &receiver->_link);
- do_send = 1;
- }
- h2o_linklist_insert(&receiver->_messages, &message->link);
- } else {
- if (h2o_linklist_is_empty(&receiver->_messages))
- do_send = 1;
- }
- pthread_mutex_unlock(&receiver->queue->mutex);
-
- if (do_send) {
-#if H2O_USE_LIBUV
- uv_async_send(&receiver->queue->async);
-#else
- while (write(receiver->queue->async.write, "", 1) == -1 && errno == EINTR)
- ;
-#endif
- }
-}
-
-void h2o_multithread_create_thread(pthread_t *tid, const pthread_attr_t *attr, void *(*func)(void *), void *arg)
-{
- if (pthread_create(tid, attr, func, arg) != 0) {
- perror("pthread_create");
- abort();
- }
-}
-
-void h2o_sem_init(h2o_sem_t *sem, ssize_t capacity)
-{
- pthread_mutex_init(&sem->_mutex, NULL);
- pthread_cond_init(&sem->_cond, NULL);
- sem->_cur = capacity;
- sem->_capacity = capacity;
-}
-
-void h2o_sem_destroy(h2o_sem_t *sem)
-{
- assert(sem->_cur == sem->_capacity);
- pthread_cond_destroy(&sem->_cond);
- pthread_mutex_destroy(&sem->_mutex);
-}
-
-void h2o_sem_wait(h2o_sem_t *sem)
-{
- pthread_mutex_lock(&sem->_mutex);
- while (sem->_cur <= 0)
- pthread_cond_wait(&sem->_cond, &sem->_mutex);
- --sem->_cur;
- pthread_mutex_unlock(&sem->_mutex);
-}
-
-void h2o_sem_post(h2o_sem_t *sem)
-{
- pthread_mutex_lock(&sem->_mutex);
- ++sem->_cur;
- pthread_cond_signal(&sem->_cond);
- pthread_mutex_unlock(&sem->_mutex);
-}
-
-void h2o_sem_set_capacity(h2o_sem_t *sem, ssize_t new_capacity)
-{
- pthread_mutex_lock(&sem->_mutex);
- sem->_cur += new_capacity - sem->_capacity;
- sem->_capacity = new_capacity;
- pthread_cond_broadcast(&sem->_cond);
- pthread_mutex_unlock(&sem->_mutex);
-}
-
-/* barrier */
-
-void h2o_barrier_init(h2o_barrier_t *barrier, size_t count)
-{
- pthread_mutex_init(&barrier->_mutex, NULL);
- pthread_cond_init(&barrier->_cond, NULL);
- barrier->_count = count;
-}
-
-int h2o_barrier_wait(h2o_barrier_t *barrier)
-{
- int ret;
- pthread_mutex_lock(&barrier->_mutex);
- barrier->_count--;
- if (barrier->_count == 0) {
- pthread_cond_broadcast(&barrier->_cond);
- ret = 1;
- } else {
- while (barrier->_count)
- pthread_cond_wait(&barrier->_cond, &barrier->_mutex);
- ret = 0;
- }
- pthread_mutex_unlock(&barrier->_mutex);
- return ret;
-}
-
-int h2o_barrier_done(h2o_barrier_t *barrier)
-{
- return __sync_add_and_fetch(&barrier->_count, 0) == 0;
-}
-
-void h2o_barrier_destroy(h2o_barrier_t *barrier)
-{
- pthread_mutex_destroy(&barrier->_mutex);
- pthread_cond_destroy(&barrier->_cond);
-}
diff --git a/web/server/h2o/libh2o/lib/common/serverutil.c b/web/server/h2o/libh2o/lib/common/serverutil.c
deleted file mode 100644
index 8226f6efc..000000000
--- a/web/server/h2o/libh2o/lib/common/serverutil.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Nick Desaulniers
- *
- * 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 <errno.h>
-#include <fcntl.h>
-#include <grp.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <signal.h>
-#include <spawn.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#if !defined(_SC_NPROCESSORS_ONLN)
-#include <sys/sysctl.h>
-#endif
-#include "cloexec.h"
-#include "h2o/memory.h"
-#include "h2o/serverutil.h"
-#include "h2o/socket.h"
-#include "h2o/string_.h"
-
-void h2o_set_signal_handler(int signo, void (*cb)(int signo))
-{
- struct sigaction action;
-
- memset(&action, 0, sizeof(action));
- sigemptyset(&action.sa_mask);
- action.sa_handler = cb;
- sigaction(signo, &action, NULL);
-}
-
-int h2o_setuidgid(const char *user)
-{
- struct passwd pwbuf, *pw;
- char buf[65536]; /* should be large enough */
-
- errno = 0;
- if (getpwnam_r(user, &pwbuf, buf, sizeof(buf), &pw) != 0) {
- perror("getpwnam_r");
- return -1;
- }
- if (pw == NULL) {
- fprintf(stderr, "unknown user:%s\n", user);
- return -1;
- }
- if (setgid(pw->pw_gid) != 0) {
- fprintf(stderr, "setgid(%d) failed:%s\n", (int)pw->pw_gid, strerror(errno));
- return -1;
- }
- if (initgroups(pw->pw_name, pw->pw_gid) != 0) {
- fprintf(stderr, "initgroups(%s, %d) failed:%s\n", pw->pw_name, (int)pw->pw_gid, strerror(errno));
- return -1;
- }
- if (setuid(pw->pw_uid) != 0) {
- fprintf(stderr, "setuid(%d) failed:%s\n", (int)pw->pw_uid, strerror(errno));
- return -1;
- }
-
- return 0;
-}
-
-size_t h2o_server_starter_get_fds(int **_fds)
-{
- const char *ports_env, *start, *end, *eq;
- size_t t;
- H2O_VECTOR(int) fds = {NULL};
-
- if ((ports_env = getenv("SERVER_STARTER_PORT")) == NULL)
- return 0;
- if (ports_env[0] == '\0') {
- fprintf(stderr, "$SERVER_STARTER_PORT is empty\n");
- return SIZE_MAX;
- }
-
- /* ports_env example: 127.0.0.1:80=3;/tmp/sock=4 */
- for (start = ports_env; *start != '\0'; start = *end == ';' ? end + 1 : end) {
- if ((end = strchr(start, ';')) == NULL)
- end = start + strlen(start);
- if ((eq = memchr(start, '=', end - start)) == NULL) {
- fprintf(stderr, "invalid $SERVER_STARTER_PORT, an element without `=` in: %s\n", ports_env);
- goto Error;
- }
- if ((t = h2o_strtosize(eq + 1, end - eq - 1)) == SIZE_MAX) {
- fprintf(stderr, "invalid file descriptor number in $SERVER_STARTER_PORT: %s\n", ports_env);
- goto Error;
- }
- h2o_vector_reserve(NULL, &fds, fds.size + 1);
- fds.entries[fds.size++] = (int)t;
- }
-
- *_fds = fds.entries;
- return fds.size;
-Error:
- free(fds.entries);
- return SIZE_MAX;
-}
-
-static char **build_spawn_env(void)
-{
- extern char **environ;
- size_t num;
-
- /* calculate number of envvars, as well as looking for H2O_ROOT= */
- for (num = 0; environ[num] != NULL; ++num)
- if (strncmp(environ[num], "H2O_ROOT=", sizeof("H2O_ROOT=") - 1) == 0)
- return NULL;
-
- /* not found */
- char **newenv = h2o_mem_alloc(sizeof(*newenv) * (num + 2) + sizeof("H2O_ROOT=" H2O_TO_STR(H2O_ROOT)));
- memcpy(newenv, environ, sizeof(*newenv) * num);
- newenv[num] = (char *)(newenv + num + 2);
- newenv[num + 1] = NULL;
- strcpy(newenv[num], "H2O_ROOT=" H2O_TO_STR(H2O_ROOT));
-
- return newenv;
-}
-
-pid_t h2o_spawnp(const char *cmd, char *const *argv, const int *mapped_fds, int cloexec_mutex_is_locked)
-{
-#if defined(__linux__)
-
- /* posix_spawnp of Linux does not return error if the executable does not exist, see
- * https://gist.github.com/kazuho/0c233e6f86d27d6e4f09
- */
- extern char **environ;
- int pipefds[2] = {-1, -1}, errnum;
- pid_t pid;
-
- /* create pipe, used for sending error codes */
- if (pipe2(pipefds, O_CLOEXEC) != 0)
- goto Error;
-
- /* fork */
- if (!cloexec_mutex_is_locked)
- pthread_mutex_lock(&cloexec_mutex);
- if ((pid = fork()) == 0) {
- /* in child process, map the file descriptors and execute; return the errnum through pipe if exec failed */
- if (mapped_fds != NULL) {
- for (; *mapped_fds != -1; mapped_fds += 2) {
- if (mapped_fds[0] != mapped_fds[1]) {
- if (mapped_fds[1] != -1)
- dup2(mapped_fds[0], mapped_fds[1]);
- close(mapped_fds[0]);
- }
- }
- }
- char **env = build_spawn_env();
- if (env != NULL)
- environ = env;
- execvp(cmd, argv);
- errnum = errno;
- write(pipefds[1], &errnum, sizeof(errnum));
- _exit(EX_SOFTWARE);
- }
- if (!cloexec_mutex_is_locked)
- pthread_mutex_unlock(&cloexec_mutex);
- if (pid == -1)
- goto Error;
-
- /* parent process */
- close(pipefds[1]);
- pipefds[1] = -1;
- ssize_t rret;
- errnum = 0;
- while ((rret = read(pipefds[0], &errnum, sizeof(errnum))) == -1 && errno == EINTR)
- ;
- if (rret != 0) {
- /* spawn failed */
- while (waitpid(pid, NULL, 0) != pid)
- ;
- pid = -1;
- errno = errnum;
- goto Error;
- }
-
- /* spawn succeeded */
- close(pipefds[0]);
- return pid;
-
-Error:
- errnum = errno;
- if (pipefds[0] != -1)
- close(pipefds[0]);
- if (pipefds[1] != -1)
- close(pipefds[1]);
- errno = errnum;
- return -1;
-
-#else
-
- posix_spawn_file_actions_t file_actions;
- pid_t pid;
- extern char **environ;
- char **env = build_spawn_env();
- posix_spawn_file_actions_init(&file_actions);
- if (mapped_fds != NULL) {
- for (; *mapped_fds != -1; mapped_fds += 2) {
- if (mapped_fds[1] != -1)
- posix_spawn_file_actions_adddup2(&file_actions, mapped_fds[0], mapped_fds[1]);
- posix_spawn_file_actions_addclose(&file_actions, mapped_fds[0]);
- }
- }
- if (!cloexec_mutex_is_locked)
- pthread_mutex_lock(&cloexec_mutex);
- errno = posix_spawnp(&pid, cmd, &file_actions, NULL, argv, env != NULL ? env : environ);
- if (!cloexec_mutex_is_locked)
- pthread_mutex_unlock(&cloexec_mutex);
- free(env);
- if (errno != 0)
- return -1;
-
- return pid;
-
-#endif
-}
-
-int h2o_read_command(const char *cmd, char **argv, h2o_buffer_t **resp, int *child_status)
-{
- int respfds[2] = {-1, -1};
- pid_t pid = -1;
- int mutex_locked = 0, ret = -1;
-
- h2o_buffer_init(resp, &h2o_socket_buffer_prototype);
-
- pthread_mutex_lock(&cloexec_mutex);
- mutex_locked = 1;
-
- /* create pipe for reading the result */
- if (pipe(respfds) != 0)
- goto Exit;
- if (fcntl(respfds[0], F_SETFD, O_CLOEXEC) < 0)
- goto Exit;
-
- /* spawn */
- int mapped_fds[] = {respfds[1], 1, /* stdout of the child process is read from the pipe */
- -1};
- if ((pid = h2o_spawnp(cmd, argv, mapped_fds, 1)) == -1)
- goto Exit;
- close(respfds[1]);
- respfds[1] = -1;
-
- pthread_mutex_unlock(&cloexec_mutex);
- mutex_locked = 0;
-
- /* read the response from pipe */
- while (1) {
- h2o_iovec_t buf = h2o_buffer_reserve(resp, 8192);
- ssize_t r;
- while ((r = read(respfds[0], buf.base, buf.len)) == -1 && errno == EINTR)
- ;
- if (r <= 0)
- break;
- (*resp)->size += r;
- }
-
-Exit:
- if (mutex_locked)
- pthread_mutex_unlock(&cloexec_mutex);
- if (pid != -1) {
- /* wait for the child to complete */
- pid_t r;
- while ((r = waitpid(pid, child_status, 0)) == -1 && errno == EINTR)
- ;
- if (r == pid) {
- /* success */
- ret = 0;
- }
- }
- if (respfds[0] != -1)
- close(respfds[0]);
- if (respfds[1] != -1)
- close(respfds[1]);
- if (ret != 0)
- h2o_buffer_dispose(resp);
-
- return ret;
-}
-
-size_t h2o_numproc(void)
-{
-#if defined(_SC_NPROCESSORS_ONLN)
- return (size_t)sysconf(_SC_NPROCESSORS_ONLN);
-#elif defined(CTL_HW) && defined(HW_AVAILCPU)
- int name[] = {CTL_HW, HW_AVAILCPU};
- int ncpu;
- size_t ncpu_sz = sizeof(ncpu);
- if (sysctl(name, sizeof(name) / sizeof(name[0]), &ncpu, &ncpu_sz, NULL, 0) != 0 || sizeof(ncpu) != ncpu_sz) {
- fprintf(stderr, "[ERROR] failed to obtain number of CPU cores, assuming as one\n");
- ncpu = 1;
- }
- return ncpu;
-#else
- return 1;
-#endif
-}
diff --git a/web/server/h2o/libh2o/lib/common/socket.c b/web/server/h2o/libh2o/lib/common/socket.c
deleted file mode 100644
index 5b1c37e04..000000000
--- a/web/server/h2o/libh2o/lib/common/socket.c
+++ /dev/null
@@ -1,1433 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku, Justin Zhu
- *
- * 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 <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <string.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include <openssl/err.h>
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
-#include <sys/ioctl.h>
-#endif
-#if H2O_USE_PICOTLS
-#include "picotls.h"
-#endif
-#include "h2o/socket.h"
-#include "h2o/timeout.h"
-
-#if defined(__APPLE__) && defined(__clang__)
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-#ifndef IOV_MAX
-#define IOV_MAX UIO_MAXIOV
-#endif
-
-/* kernel-headers bundled with Ubuntu 14.04 does not have the constant defined in netinet/tcp.h */
-#if defined(__linux__) && !defined(TCP_NOTSENT_LOWAT)
-#define TCP_NOTSENT_LOWAT 25
-#endif
-
-#define OPENSSL_HOSTNAME_VALIDATION_LINKAGE static
-#include "../../deps/ssl-conservatory/openssl/openssl_hostname_validation.c"
-
-struct st_h2o_socket_ssl_t {
- SSL_CTX *ssl_ctx;
- SSL *ossl;
-#if H2O_USE_PICOTLS
- ptls_t *ptls;
-#endif
- int *did_write_in_read; /* used for detecting and closing the connection upon renegotiation (FIXME implement renegotiation) */
- size_t record_overhead;
- struct {
- h2o_socket_cb cb;
- union {
- struct {
- struct {
- enum {
- ASYNC_RESUMPTION_STATE_COMPLETE = 0, /* just pass thru */
- ASYNC_RESUMPTION_STATE_RECORD, /* record first input, restore SSL state if it changes to REQUEST_SENT
- */
- ASYNC_RESUMPTION_STATE_REQUEST_SENT /* async request has been sent, and is waiting for response */
- } state;
- SSL_SESSION *session_data;
- } async_resumption;
- } server;
- struct {
- char *server_name;
- h2o_cache_t *session_cache;
- h2o_iovec_t session_cache_key;
- h2o_cache_hashcode_t session_cache_key_hash;
- } client;
- };
- } handshake;
- struct {
- h2o_buffer_t *encrypted;
- } input;
- struct {
- H2O_VECTOR(h2o_iovec_t) bufs;
- h2o_mem_pool_t pool; /* placed at the last */
- } output;
-};
-
-struct st_h2o_ssl_context_t {
- SSL_CTX *ctx;
- const h2o_iovec_t *protocols;
- h2o_iovec_t _npn_list_of_protocols;
-};
-
-/* backend functions */
-static void do_dispose_socket(h2o_socket_t *sock);
-static void do_write(h2o_socket_t *sock, h2o_iovec_t *bufs, size_t bufcnt, h2o_socket_cb cb);
-static void do_read_start(h2o_socket_t *sock);
-static void do_read_stop(h2o_socket_t *sock);
-static int do_export(h2o_socket_t *_sock, h2o_socket_export_t *info);
-static h2o_socket_t *do_import(h2o_loop_t *loop, h2o_socket_export_t *info);
-static socklen_t get_peername_uncached(h2o_socket_t *sock, struct sockaddr *sa);
-
-/* internal functions called from the backend */
-static const char *decode_ssl_input(h2o_socket_t *sock);
-static void on_write_complete(h2o_socket_t *sock, const char *err);
-
-#if H2O_USE_LIBUV
-#include "socket/uv-binding.c.h"
-#else
-#include "socket/evloop.c.h"
-#endif
-
-h2o_buffer_mmap_settings_t h2o_socket_buffer_mmap_settings = {
- 32 * 1024 * 1024, /* 32MB, should better be greater than max frame size of HTTP2 for performance reasons */
- "/tmp/h2o.b.XXXXXX"};
-
-__thread h2o_buffer_prototype_t h2o_socket_buffer_prototype = {
- {16}, /* keep 16 recently used chunks */
- {H2O_SOCKET_INITIAL_INPUT_BUFFER_SIZE * 2}, /* minimum initial capacity */
- &h2o_socket_buffer_mmap_settings};
-
-const char *h2o_socket_error_out_of_memory = "out of memory";
-const char *h2o_socket_error_io = "I/O error";
-const char *h2o_socket_error_closed = "socket closed by peer";
-const char *h2o_socket_error_conn_fail = "connection failure";
-const char *h2o_socket_error_ssl_no_cert = "no certificate";
-const char *h2o_socket_error_ssl_cert_invalid = "invalid certificate";
-const char *h2o_socket_error_ssl_cert_name_mismatch = "certificate name mismatch";
-const char *h2o_socket_error_ssl_decode = "SSL decode error";
-
-static void (*resumption_get_async)(h2o_socket_t *sock, h2o_iovec_t session_id);
-static void (*resumption_new)(h2o_iovec_t session_id, h2o_iovec_t session_data);
-
-static int read_bio(BIO *b, char *out, int len)
-{
- h2o_socket_t *sock = BIO_get_data(b);
-
- if (len == 0)
- return 0;
-
- if (sock->ssl->input.encrypted->size == 0) {
- BIO_set_retry_read(b);
- return -1;
- }
-
- if (sock->ssl->input.encrypted->size < len) {
- len = (int)sock->ssl->input.encrypted->size;
- }
- memcpy(out, sock->ssl->input.encrypted->bytes, len);
- h2o_buffer_consume(&sock->ssl->input.encrypted, len);
-
- return len;
-}
-
-static void write_ssl_bytes(h2o_socket_t *sock, const void *in, size_t len)
-{
- if (len != 0) {
- void *bytes_alloced = h2o_mem_alloc_pool(&sock->ssl->output.pool, len);
- memcpy(bytes_alloced, in, len);
- h2o_vector_reserve(&sock->ssl->output.pool, &sock->ssl->output.bufs, sock->ssl->output.bufs.size + 1);
- sock->ssl->output.bufs.entries[sock->ssl->output.bufs.size++] = h2o_iovec_init(bytes_alloced, len);
- }
-}
-
-static int write_bio(BIO *b, const char *in, int len)
-{
- h2o_socket_t *sock = BIO_get_data(b);
-
- /* FIXME no support for SSL renegotiation (yet) */
- if (sock->ssl->did_write_in_read != NULL) {
- *sock->ssl->did_write_in_read = 1;
- return -1;
- }
-
- write_ssl_bytes(sock, in, len);
- return len;
-}
-
-static int puts_bio(BIO *b, const char *str)
-{
- return write_bio(b, str, (int)strlen(str));
-}
-
-static long ctrl_bio(BIO *b, int cmd, long num, void *ptr)
-{
- switch (cmd) {
- case BIO_CTRL_GET_CLOSE:
- return BIO_get_shutdown(b);
- case BIO_CTRL_SET_CLOSE:
- BIO_set_shutdown(b, (int)num);
- return 1;
- case BIO_CTRL_FLUSH:
- return 1;
- default:
- return 0;
- }
-}
-
-static void setup_bio(h2o_socket_t *sock)
-{
- static BIO_METHOD *bio_methods = NULL;
- if (bio_methods == NULL) {
- static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;
- pthread_mutex_lock(&init_lock);
- if (bio_methods == NULL) {
- BIO_METHOD *biom = BIO_meth_new(BIO_TYPE_FD, "h2o_socket");
- BIO_meth_set_write(biom, write_bio);
- BIO_meth_set_read(biom, read_bio);
- BIO_meth_set_puts(biom, puts_bio);
- BIO_meth_set_ctrl(biom, ctrl_bio);
- __sync_synchronize();
- bio_methods = biom;
- }
- pthread_mutex_unlock(&init_lock);
- }
-
- BIO *bio = BIO_new(bio_methods);
- if (bio == NULL)
- h2o_fatal("no memory");
- BIO_set_data(bio, sock);
- BIO_set_init(bio, 1);
- SSL_set_bio(sock->ssl->ossl, bio, bio);
-}
-
-const char *decode_ssl_input(h2o_socket_t *sock)
-{
- assert(sock->ssl != NULL);
- assert(sock->ssl->handshake.cb == NULL);
-
-#if H2O_USE_PICOTLS
- if (sock->ssl->ptls != NULL) {
- if (sock->ssl->input.encrypted->size != 0) {
- const char *src = sock->ssl->input.encrypted->bytes, *src_end = src + sock->ssl->input.encrypted->size;
- h2o_iovec_t reserved;
- ptls_buffer_t rbuf;
- int ret;
- if ((reserved = h2o_buffer_reserve(&sock->input, sock->ssl->input.encrypted->size)).base == NULL)
- return h2o_socket_error_out_of_memory;
- ptls_buffer_init(&rbuf, reserved.base, reserved.len);
- do {
- size_t consumed = src_end - src;
- if ((ret = ptls_receive(sock->ssl->ptls, &rbuf, src, &consumed)) != 0)
- break;
- src += consumed;
- } while (src != src_end);
- h2o_buffer_consume(&sock->ssl->input.encrypted, sock->ssl->input.encrypted->size - (src_end - src));
- if (rbuf.is_allocated) {
- if ((reserved = h2o_buffer_reserve(&sock->input, rbuf.off)).base == NULL)
- return h2o_socket_error_out_of_memory;
- memcpy(reserved.base, rbuf.base, rbuf.off);
- sock->input->size += rbuf.off;
- ptls_buffer_dispose(&rbuf);
- } else {
- sock->input->size += rbuf.off;
- }
- if (!(ret == 0 || ret == PTLS_ERROR_IN_PROGRESS))
- return h2o_socket_error_ssl_decode;
- }
- return NULL;
- }
-#endif
-
- while (sock->ssl->input.encrypted->size != 0 || SSL_pending(sock->ssl->ossl)) {
- int rlen;
- h2o_iovec_t buf = h2o_buffer_reserve(&sock->input, 4096);
- if (buf.base == NULL)
- return h2o_socket_error_out_of_memory;
- { /* call SSL_read (while detecting SSL renegotiation and reporting it as error) */
- int did_write_in_read = 0;
- sock->ssl->did_write_in_read = &did_write_in_read;
- ERR_clear_error();
- rlen = SSL_read(sock->ssl->ossl, buf.base, (int)buf.len);
- sock->ssl->did_write_in_read = NULL;
- if (did_write_in_read)
- return "ssl renegotiation not supported";
- }
- if (rlen == -1) {
- if (SSL_get_error(sock->ssl->ossl, rlen) != SSL_ERROR_WANT_READ) {
- return h2o_socket_error_ssl_decode;
- }
- break;
- } else if (rlen == 0) {
- break;
- } else {
- sock->input->size += rlen;
- }
- }
-
- return 0;
-}
-
-static void flush_pending_ssl(h2o_socket_t *sock, h2o_socket_cb cb)
-{
- do_write(sock, sock->ssl->output.bufs.entries, sock->ssl->output.bufs.size, cb);
-}
-
-static void clear_output_buffer(struct st_h2o_socket_ssl_t *ssl)
-{
- memset(&ssl->output.bufs, 0, sizeof(ssl->output.bufs));
- h2o_mem_clear_pool(&ssl->output.pool);
-}
-
-static void destroy_ssl(struct st_h2o_socket_ssl_t *ssl)
-{
-#if H2O_USE_PICOTLS
- if (ssl->ptls != NULL) {
- ptls_free(ssl->ptls);
- ssl->ptls = NULL;
- }
-#endif
- if (ssl->ossl != NULL) {
- if (!SSL_is_server(ssl->ossl)) {
- free(ssl->handshake.client.server_name);
- free(ssl->handshake.client.session_cache_key.base);
- }
- SSL_free(ssl->ossl);
- ssl->ossl = NULL;
- }
- h2o_buffer_dispose(&ssl->input.encrypted);
- clear_output_buffer(ssl);
- free(ssl);
-}
-
-static void dispose_socket(h2o_socket_t *sock, const char *err)
-{
- void (*close_cb)(void *data);
- void *close_cb_data;
-
- if (sock->ssl != NULL) {
- destroy_ssl(sock->ssl);
- sock->ssl = NULL;
- }
- h2o_buffer_dispose(&sock->input);
- if (sock->_peername != NULL) {
- free(sock->_peername);
- sock->_peername = NULL;
- }
-
- close_cb = sock->on_close.cb;
- close_cb_data = sock->on_close.data;
-
- do_dispose_socket(sock);
-
- if (close_cb != NULL)
- close_cb(close_cb_data);
-}
-
-static void shutdown_ssl(h2o_socket_t *sock, const char *err)
-{
- int ret;
-
- if (err != NULL)
- goto Close;
-
- if (sock->_cb.write != NULL) {
- /* note: libuv calls the write callback after the socket is closed by uv_close (with status set to 0 if the write succeeded)
- */
- sock->_cb.write = NULL;
- goto Close;
- }
-
-#if H2O_USE_PICOTLS
- if (sock->ssl->ptls != NULL) {
- ptls_buffer_t wbuf;
- uint8_t wbuf_small[32];
- ptls_buffer_init(&wbuf, wbuf_small, sizeof(wbuf_small));
- if ((ret = ptls_send_alert(sock->ssl->ptls, &wbuf, PTLS_ALERT_LEVEL_WARNING, PTLS_ALERT_CLOSE_NOTIFY)) != 0)
- goto Close;
- write_ssl_bytes(sock, wbuf.base, wbuf.off);
- ptls_buffer_dispose(&wbuf);
- ret = 1; /* close the socket after sending close_notify */
- } else
-#endif
- if (sock->ssl->ossl != NULL) {
- ERR_clear_error();
- if ((ret = SSL_shutdown(sock->ssl->ossl)) == -1)
- goto Close;
- } else {
- goto Close;
- }
-
- if (sock->ssl->output.bufs.size != 0) {
- h2o_socket_read_stop(sock);
- flush_pending_ssl(sock, ret == 1 ? dispose_socket : shutdown_ssl);
- } else if (ret == 2 && SSL_get_error(sock->ssl->ossl, ret) == SSL_ERROR_WANT_READ) {
- h2o_socket_read_start(sock, shutdown_ssl);
- } else {
- goto Close;
- }
-
- return;
-Close:
- dispose_socket(sock, err);
-}
-
-void h2o_socket_dispose_export(h2o_socket_export_t *info)
-{
- assert(info->fd != -1);
- if (info->ssl != NULL) {
- destroy_ssl(info->ssl);
- info->ssl = NULL;
- }
- h2o_buffer_dispose(&info->input);
- close(info->fd);
- info->fd = -1;
-}
-
-int h2o_socket_export(h2o_socket_t *sock, h2o_socket_export_t *info)
-{
- static h2o_buffer_prototype_t nonpooling_prototype;
-
- assert(!h2o_socket_is_writing(sock));
-
- if (do_export(sock, info) == -1)
- return -1;
-
- if ((info->ssl = sock->ssl) != NULL) {
- sock->ssl = NULL;
- h2o_buffer_set_prototype(&info->ssl->input.encrypted, &nonpooling_prototype);
- }
- info->input = sock->input;
- h2o_buffer_set_prototype(&info->input, &nonpooling_prototype);
- h2o_buffer_init(&sock->input, &h2o_socket_buffer_prototype);
-
- h2o_socket_close(sock);
-
- return 0;
-}
-
-h2o_socket_t *h2o_socket_import(h2o_loop_t *loop, h2o_socket_export_t *info)
-{
- h2o_socket_t *sock;
-
- assert(info->fd != -1);
-
- sock = do_import(loop, info);
- info->fd = -1; /* just in case */
- if ((sock->ssl = info->ssl) != NULL) {
- setup_bio(sock);
- h2o_buffer_set_prototype(&sock->ssl->input.encrypted, &h2o_socket_buffer_prototype);
- }
- sock->input = info->input;
- h2o_buffer_set_prototype(&sock->input, &h2o_socket_buffer_prototype);
- return sock;
-}
-
-void h2o_socket_close(h2o_socket_t *sock)
-{
- if (sock->ssl == NULL) {
- dispose_socket(sock, 0);
- } else {
- shutdown_ssl(sock, 0);
- }
-}
-
-static uint16_t calc_suggested_tls_payload_size(h2o_socket_t *sock, uint16_t suggested_tls_record_size)
-{
- uint16_t ps = suggested_tls_record_size;
- if (sock->ssl != NULL && sock->ssl->record_overhead < ps)
- ps -= sock->ssl->record_overhead;
- return ps;
-}
-
-static void disable_latency_optimized_write(h2o_socket_t *sock, int (*adjust_notsent_lowat)(h2o_socket_t *, unsigned))
-{
- if (sock->_latency_optimization.notsent_is_minimized) {
- adjust_notsent_lowat(sock, 0);
- sock->_latency_optimization.notsent_is_minimized = 0;
- }
- sock->_latency_optimization.state = H2O_SOCKET_LATENCY_OPTIMIZATION_STATE_DISABLED;
- sock->_latency_optimization.suggested_tls_payload_size = 16384;
- sock->_latency_optimization.suggested_write_size = SIZE_MAX;
-}
-
-static inline void prepare_for_latency_optimized_write(h2o_socket_t *sock,
- const h2o_socket_latency_optimization_conditions_t *conditions, uint32_t rtt,
- uint32_t mss, uint32_t cwnd_size, uint32_t cwnd_avail, uint64_t loop_time,
- int (*adjust_notsent_lowat)(h2o_socket_t *, unsigned))
-{
- /* check RTT */
- if (rtt < conditions->min_rtt * (uint64_t)1000)
- goto Disable;
- if (rtt * conditions->max_additional_delay < loop_time * 1000 * 100)
- goto Disable;
-
- /* latency-optimization is enabled */
- sock->_latency_optimization.state = H2O_SOCKET_LATENCY_OPTIMIZATION_STATE_DETERMINED;
-
- /* no need to:
- * 1) adjust the write size if single_write_size << cwnd_size
- * 2) align TLS record boundary to TCP packet boundary if packet loss-rate is low and BW isn't small (implied by cwnd size)
- */
- if (mss * cwnd_size < conditions->max_cwnd) {
- if (!sock->_latency_optimization.notsent_is_minimized) {
- if (adjust_notsent_lowat(sock, 1 /* cannot be set to zero on Linux */) != 0)
- goto Disable;
- sock->_latency_optimization.notsent_is_minimized = 1;
- }
- sock->_latency_optimization.suggested_tls_payload_size = calc_suggested_tls_payload_size(sock, mss);
- sock->_latency_optimization.suggested_write_size =
- cwnd_avail * (size_t)sock->_latency_optimization.suggested_tls_payload_size;
- } else {
- if (sock->_latency_optimization.notsent_is_minimized) {
- if (adjust_notsent_lowat(sock, 0) != 0)
- goto Disable;
- sock->_latency_optimization.notsent_is_minimized = 0;
- }
- sock->_latency_optimization.suggested_tls_payload_size = 16384;
- sock->_latency_optimization.suggested_write_size = SIZE_MAX;
- }
- return;
-
-Disable:
- disable_latency_optimized_write(sock, adjust_notsent_lowat);
-}
-
-/**
- * Obtains RTT, MSS, size of CWND (in the number of packets).
- * Also writes to cwnd_avail minimum number of packets (of MSS size) sufficient to shut up poll-for-write under the precondition
- * that TCP_NOTSENT_LOWAT is set to 1.
- */
-static int obtain_tcp_info(int fd, uint32_t *rtt, uint32_t *mss, uint32_t *cwnd_size, uint32_t *cwnd_avail)
-{
-#define CALC_CWND_PAIR_FROM_BYTE_UNITS(cwnd_bytes, inflight_bytes) \
- do { \
- *cwnd_size = (cwnd_bytes + *mss / 2) / *mss; \
- *cwnd_avail = cwnd_bytes > inflight_bytes ? (cwnd_bytes - inflight_bytes) / *mss + 2 : 2; \
- } while (0)
-
-#if defined(__linux__) && defined(TCP_INFO)
-
- struct tcp_info tcpi;
- socklen_t tcpisz = sizeof(tcpi);
- if (getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcpi, &tcpisz) != 0)
- return -1;
- *rtt = tcpi.tcpi_rtt;
- *mss = tcpi.tcpi_snd_mss;
- *cwnd_size = tcpi.tcpi_snd_cwnd;
- *cwnd_avail = tcpi.tcpi_snd_cwnd > tcpi.tcpi_unacked ? tcpi.tcpi_snd_cwnd - tcpi.tcpi_unacked + 2 : 2;
- return 0;
-
-#elif defined(__FreeBSD__) && defined(TCP_INFO) && 0 /* disabled since we wouldn't use it anyways; OS lacks TCP_NOTSENT_LOWAT */
-
- struct tcp_info tcpi;
- socklen_t tcpisz = sizeof(tcpi);
- int bytes_inflight;
- if (getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcpi, &tcpisz) != 0 || ioctl(fd, FIONWRITE, &bytes_inflight) == -1)
- return -1;
- *rtt = tcpi.tcpi_rtt;
- *mss = tcpi.tcpi_snd_mss;
- CALC_CWND_PAIR_FROM_BYTE_UNITS(tcpi.tcpi_snd_cwnd, bytes_inflight);
- return 0;
-
-#elif defined(__APPLE__) && defined(TCP_CONNECTION_INFO)
-
- struct tcp_connection_info tcpi;
- socklen_t tcpisz = sizeof(tcpi);
- if (getsockopt(fd, IPPROTO_TCP, TCP_CONNECTION_INFO, &tcpi, &tcpisz) != 0 || tcpi.tcpi_maxseg == 0)
- return -1;
- *rtt = tcpi.tcpi_srtt * 1000;
- *mss = tcpi.tcpi_maxseg;
- CALC_CWND_PAIR_FROM_BYTE_UNITS(tcpi.tcpi_snd_cwnd, tcpi.tcpi_snd_sbbytes);
- return 0;
-
-#else
- /* TODO add support for NetBSD; note that the OS returns the number of packets for tcpi_snd_cwnd; see
- * http://twitter.com/n_soda/status/740719125878575105
- */
- return -1;
-#endif
-
-#undef CALC_CWND_PAIR_FROM_BYTE_UNITS
-}
-
-#ifdef TCP_NOTSENT_LOWAT
-static int adjust_notsent_lowat(h2o_socket_t *sock, unsigned notsent_lowat)
-{
- return setsockopt(h2o_socket_get_fd(sock), IPPROTO_TCP, TCP_NOTSENT_LOWAT, &notsent_lowat, sizeof(notsent_lowat));
-}
-#else
-#define adjust_notsent_lowat NULL
-#endif
-
-size_t h2o_socket_do_prepare_for_latency_optimized_write(h2o_socket_t *sock,
- const h2o_socket_latency_optimization_conditions_t *conditions)
-{
- uint32_t rtt = 0, mss = 0, cwnd_size = 0, cwnd_avail = 0;
- uint64_t loop_time = UINT64_MAX;
- int can_prepare = 1;
-
-#if !defined(TCP_NOTSENT_LOWAT)
- /* the feature cannot be setup unless TCP_NOTSENT_LOWAT is available */
- can_prepare = 0;
-#endif
-
-#if H2O_USE_LIBUV
- /* poll-then-write is impossible with libuv */
- can_prepare = 0;
-#else
- if (can_prepare)
- loop_time = h2o_evloop_get_execution_time(h2o_socket_get_loop(sock));
-#endif
-
- /* obtain TCP states */
- if (can_prepare && obtain_tcp_info(h2o_socket_get_fd(sock), &rtt, &mss, &cwnd_size, &cwnd_avail) != 0)
- can_prepare = 0;
-
- /* determine suggested_write_size, suggested_tls_record_size and adjust TCP_NOTSENT_LOWAT based on the obtained information */
- if (can_prepare) {
- prepare_for_latency_optimized_write(sock, conditions, rtt, mss, cwnd_size, cwnd_avail, loop_time, adjust_notsent_lowat);
- } else {
- disable_latency_optimized_write(sock, adjust_notsent_lowat);
- }
-
- return sock->_latency_optimization.suggested_write_size;
-
-#undef CALC_CWND_PAIR_FROM_BYTE_UNITS
-}
-
-void h2o_socket_write(h2o_socket_t *sock, h2o_iovec_t *bufs, size_t bufcnt, h2o_socket_cb cb)
-{
- size_t i, prev_bytes_written = sock->bytes_written;
-
- for (i = 0; i != bufcnt; ++i) {
- sock->bytes_written += bufs[i].len;
-#if H2O_SOCKET_DUMP_WRITE
- fprintf(stderr, "writing %zu bytes to fd:%d\n", bufs[i].len, h2o_socket_get_fd(sock));
- h2o_dump_memory(stderr, bufs[i].base, bufs[i].len);
-#endif
- }
-
- if (sock->ssl == NULL) {
- do_write(sock, bufs, bufcnt, cb);
- } else {
- assert(sock->ssl->output.bufs.size == 0);
- /* fill in the data */
- size_t ssl_record_size;
- switch (sock->_latency_optimization.state) {
- case H2O_SOCKET_LATENCY_OPTIMIZATION_STATE_TBD:
- case H2O_SOCKET_LATENCY_OPTIMIZATION_STATE_DISABLED:
- ssl_record_size = prev_bytes_written < 200 * 1024 ? calc_suggested_tls_payload_size(sock, 1400) : 16384;
- break;
- case H2O_SOCKET_LATENCY_OPTIMIZATION_STATE_DETERMINED:
- sock->_latency_optimization.state = H2O_SOCKET_LATENCY_OPTIMIZATION_STATE_NEEDS_UPDATE;
- /* fallthru */
- default:
- ssl_record_size = sock->_latency_optimization.suggested_tls_payload_size;
- break;
- }
- for (; bufcnt != 0; ++bufs, --bufcnt) {
- size_t off = 0;
- while (off != bufs[0].len) {
- int ret;
- size_t sz = bufs[0].len - off;
- if (sz > ssl_record_size)
- sz = ssl_record_size;
-#if H2O_USE_PICOTLS
- if (sock->ssl->ptls != NULL) {
- size_t dst_size = sz + ptls_get_record_overhead(sock->ssl->ptls);
- void *dst = h2o_mem_alloc_pool(&sock->ssl->output.pool, dst_size);
- ptls_buffer_t wbuf;
- ptls_buffer_init(&wbuf, dst, dst_size);
- ret = ptls_send(sock->ssl->ptls, &wbuf, bufs[0].base + off, sz);
- assert(ret == 0);
- assert(!wbuf.is_allocated);
- h2o_vector_reserve(&sock->ssl->output.pool, &sock->ssl->output.bufs, sock->ssl->output.bufs.size + 1);
- sock->ssl->output.bufs.entries[sock->ssl->output.bufs.size++] = h2o_iovec_init(dst, wbuf.off);
- } else
-#endif
- {
- ret = SSL_write(sock->ssl->ossl, bufs[0].base + off, (int)sz);
- if (ret != sz) {
- /* The error happens if SSL_write is called after SSL_read returns a fatal error (e.g. due to corrupt TCP
- * packet being received). We need to take care of this since some protocol implementations send data after
- * the read-side of the connection gets closed (note that protocol implementations are (yet) incapable of
- * distinguishing a normal shutdown and close due to an error using the `status` value of the read
- * callback).
- */
- clear_output_buffer(sock->ssl);
- flush_pending_ssl(sock, cb);
-#ifndef H2O_USE_LIBUV
- ((struct st_h2o_evloop_socket_t *)sock)->_flags |= H2O_SOCKET_FLAG_IS_WRITE_ERROR;
-#endif
- return;
- }
- }
- off += sz;
- }
- }
- flush_pending_ssl(sock, cb);
- }
-}
-
-void on_write_complete(h2o_socket_t *sock, const char *err)
-{
- h2o_socket_cb cb;
-
- if (sock->ssl != NULL)
- clear_output_buffer(sock->ssl);
-
- cb = sock->_cb.write;
- sock->_cb.write = NULL;
- cb(sock, err);
-}
-
-void h2o_socket_read_start(h2o_socket_t *sock, h2o_socket_cb cb)
-{
- sock->_cb.read = cb;
- do_read_start(sock);
-}
-
-void h2o_socket_read_stop(h2o_socket_t *sock)
-{
- sock->_cb.read = NULL;
- do_read_stop(sock);
-}
-
-void h2o_socket_setpeername(h2o_socket_t *sock, struct sockaddr *sa, socklen_t len)
-{
- if (sock->_peername != NULL)
- free(sock->_peername);
- sock->_peername = h2o_mem_alloc(offsetof(struct st_h2o_socket_peername_t, addr) + len);
- sock->_peername->len = len;
- memcpy(&sock->_peername->addr, sa, len);
-}
-
-socklen_t h2o_socket_getpeername(h2o_socket_t *sock, struct sockaddr *sa)
-{
- /* return cached, if exists */
- if (sock->_peername != NULL) {
- memcpy(sa, &sock->_peername->addr, sock->_peername->len);
- return sock->_peername->len;
- }
- /* call, copy to cache, and return */
- socklen_t len = get_peername_uncached(sock, sa);
- h2o_socket_setpeername(sock, sa, len);
- return len;
-}
-
-const char *h2o_socket_get_ssl_protocol_version(h2o_socket_t *sock)
-{
- if (sock->ssl != NULL) {
-#if H2O_USE_PICOTLS
- if (sock->ssl->ptls != NULL)
- return "TLSv1.3";
-#endif
- if (sock->ssl->ossl != NULL)
- return SSL_get_version(sock->ssl->ossl);
- }
- return NULL;
-}
-
-int h2o_socket_get_ssl_session_reused(h2o_socket_t *sock)
-{
- if (sock->ssl != NULL) {
-#if H2O_USE_PICOTLS
- if (sock->ssl->ptls != NULL)
- return ptls_is_psk_handshake(sock->ssl->ptls);
-#endif
- if (sock->ssl->ossl != NULL)
- return (int)SSL_session_reused(sock->ssl->ossl);
- }
- return -1;
-}
-
-const char *h2o_socket_get_ssl_cipher(h2o_socket_t *sock)
-{
- if (sock->ssl != NULL) {
-#if H2O_USE_PICOTLS
- if (sock->ssl->ptls != NULL) {
- ptls_cipher_suite_t *cipher = ptls_get_cipher(sock->ssl->ptls);
- if (cipher != NULL)
- return cipher->aead->name;
- } else
-#endif
- if (sock->ssl->ossl != NULL)
- return SSL_get_cipher_name(sock->ssl->ossl);
- }
- return NULL;
-}
-
-int h2o_socket_get_ssl_cipher_bits(h2o_socket_t *sock)
-{
- if (sock->ssl != NULL) {
-#if H2O_USE_PICOTLS
- if (sock->ssl->ptls != NULL) {
- ptls_cipher_suite_t *cipher = ptls_get_cipher(sock->ssl->ptls);
- if (cipher == NULL)
- return 0;
- return (int)cipher->aead->key_size;
- } else
-#endif
- if (sock->ssl->ossl != NULL)
- return SSL_get_cipher_bits(sock->ssl->ossl, NULL);
- }
- return 0;
-}
-
-h2o_iovec_t h2o_socket_get_ssl_session_id(h2o_socket_t *sock)
-{
- if (sock->ssl != NULL) {
-#if H2O_USE_PICOTLS
- if (sock->ssl->ptls != NULL) {
- /* FIXME */
- } else
-#endif
- if (sock->ssl->ossl != NULL) {
- SSL_SESSION *session;
- if (sock->ssl->handshake.server.async_resumption.state == ASYNC_RESUMPTION_STATE_COMPLETE &&
- (session = SSL_get_session(sock->ssl->ossl)) != NULL) {
- unsigned id_len;
- const unsigned char *id = SSL_SESSION_get_id(session, &id_len);
- return h2o_iovec_init(id, id_len);
- }
- }
- }
-
- return h2o_iovec_init(NULL, 0);
-}
-
-h2o_iovec_t h2o_socket_log_ssl_session_id(h2o_socket_t *sock, h2o_mem_pool_t *pool)
-{
- h2o_iovec_t base64id, rawid = h2o_socket_get_ssl_session_id(sock);
-
- if (rawid.base == NULL)
- return h2o_iovec_init(NULL, 0);
-
- base64id.base = pool != NULL ? h2o_mem_alloc_pool(pool, h2o_base64_encode_capacity(rawid.len))
- : h2o_mem_alloc(h2o_base64_encode_capacity(rawid.len));
- base64id.len = h2o_base64_encode(base64id.base, rawid.base, rawid.len, 1);
- return base64id;
-}
-
-h2o_iovec_t h2o_socket_log_ssl_cipher_bits(h2o_socket_t *sock, h2o_mem_pool_t *pool)
-{
- int bits = h2o_socket_get_ssl_cipher_bits(sock);
- if (bits != 0) {
- char *s = (char *)(pool != NULL ? h2o_mem_alloc_pool(pool, sizeof(H2O_INT16_LONGEST_STR))
- : h2o_mem_alloc(sizeof(H2O_INT16_LONGEST_STR)));
- size_t len = sprintf(s, "%" PRId16, (int16_t)bits);
- return h2o_iovec_init(s, len);
- } else {
- return h2o_iovec_init(NULL, 0);
- }
-}
-
-int h2o_socket_compare_address(struct sockaddr *x, struct sockaddr *y)
-{
-#define CMP(a, b) \
- if (a != b) \
- return a < b ? -1 : 1
-
- CMP(x->sa_family, y->sa_family);
-
- if (x->sa_family == AF_UNIX) {
- struct sockaddr_un *xun = (void *)x, *yun = (void *)y;
- int r = strcmp(xun->sun_path, yun->sun_path);
- if (r != 0)
- return r;
- } else if (x->sa_family == AF_INET) {
- struct sockaddr_in *xin = (void *)x, *yin = (void *)y;
- CMP(ntohl(xin->sin_addr.s_addr), ntohl(yin->sin_addr.s_addr));
- CMP(ntohs(xin->sin_port), ntohs(yin->sin_port));
- } else if (x->sa_family == AF_INET6) {
- struct sockaddr_in6 *xin6 = (void *)x, *yin6 = (void *)y;
- int r = memcmp(xin6->sin6_addr.s6_addr, yin6->sin6_addr.s6_addr, sizeof(xin6->sin6_addr.s6_addr));
- if (r != 0)
- return r;
- CMP(ntohs(xin6->sin6_port), ntohs(yin6->sin6_port));
- CMP(xin6->sin6_flowinfo, yin6->sin6_flowinfo);
- CMP(xin6->sin6_scope_id, yin6->sin6_scope_id);
- } else {
- assert(!"unknown sa_family");
- }
-
-#undef CMP
- return 0;
-}
-
-size_t h2o_socket_getnumerichost(struct sockaddr *sa, socklen_t salen, char *buf)
-{
- if (sa->sa_family == AF_INET) {
- /* fast path for IPv4 addresses */
- struct sockaddr_in *sin = (void *)sa;
- uint32_t addr;
- addr = htonl(sin->sin_addr.s_addr);
- return sprintf(buf, "%d.%d.%d.%d", addr >> 24, (addr >> 16) & 255, (addr >> 8) & 255, addr & 255);
- }
-
- if (getnameinfo(sa, salen, buf, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) != 0)
- return SIZE_MAX;
- return strlen(buf);
-}
-
-int32_t h2o_socket_getport(struct sockaddr *sa)
-{
- switch (sa->sa_family) {
- case AF_INET:
- return htons(((struct sockaddr_in *)sa)->sin_port);
- case AF_INET6:
- return htons(((struct sockaddr_in6 *)sa)->sin6_port);
- default:
- return -1;
- }
-}
-
-static void create_ossl(h2o_socket_t *sock)
-{
- sock->ssl->ossl = SSL_new(sock->ssl->ssl_ctx);
- setup_bio(sock);
-}
-
-static SSL_SESSION *on_async_resumption_get(SSL *ssl,
-#if OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined(LIBRESSL_VERSION_NUMBER)
- const
-#endif
- unsigned char *data,
- int len, int *copy)
-{
- h2o_socket_t *sock = BIO_get_data(SSL_get_rbio(ssl));
-
- switch (sock->ssl->handshake.server.async_resumption.state) {
- case ASYNC_RESUMPTION_STATE_RECORD:
- sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_REQUEST_SENT;
- resumption_get_async(sock, h2o_iovec_init(data, len));
- return NULL;
- case ASYNC_RESUMPTION_STATE_COMPLETE:
- *copy = 1;
- return sock->ssl->handshake.server.async_resumption.session_data;
- default:
- assert(!"FIXME");
- return NULL;
- }
-}
-
-static int on_async_resumption_new(SSL *ssl, SSL_SESSION *session)
-{
- h2o_iovec_t data;
- const unsigned char *id;
- unsigned id_len;
- unsigned char *p;
-
- /* build data */
- data.len = i2d_SSL_SESSION(session, NULL);
- data.base = alloca(data.len);
- p = (void *)data.base;
- i2d_SSL_SESSION(session, &p);
-
- id = SSL_SESSION_get_id(session, &id_len);
- resumption_new(h2o_iovec_init(id, id_len), data);
- return 0;
-}
-
-static void on_handshake_complete(h2o_socket_t *sock, const char *err)
-{
- if (err == NULL) {
-#if H2O_USE_PICOTLS
- if (sock->ssl->ptls != NULL) {
- sock->ssl->record_overhead = ptls_get_record_overhead(sock->ssl->ptls);
- } else
-#endif
- {
- const SSL_CIPHER *cipher = SSL_get_current_cipher(sock->ssl->ossl);
- switch (SSL_CIPHER_get_id(cipher)) {
- case TLS1_CK_RSA_WITH_AES_128_GCM_SHA256:
- case TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256:
- case TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- case TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- case TLS1_CK_RSA_WITH_AES_256_GCM_SHA384:
- case TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384:
- case TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
- case TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
- sock->ssl->record_overhead = 5 /* header */ + 8 /* record_iv_length (RFC 5288 3) */ + 16 /* tag (RFC 5116 5.1) */;
- break;
-#if defined(TLS1_CK_DHE_RSA_CHACHA20_POLY1305)
- case TLS1_CK_DHE_RSA_CHACHA20_POLY1305:
- case TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305:
- case TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305:
- sock->ssl->record_overhead = 5 /* header */ + 16 /* tag */;
- break;
-#endif
- default:
- sock->ssl->record_overhead = 32; /* sufficiently large number that can hold most payloads */
- break;
- }
- }
- }
-
- /* set ssl session into the cache */
- if (sock->ssl->ossl != NULL && !SSL_is_server(sock->ssl->ossl) && sock->ssl->handshake.client.session_cache != NULL) {
- if (err == NULL || err == h2o_socket_error_ssl_cert_name_mismatch) {
- SSL_SESSION *session = SSL_get1_session(sock->ssl->ossl);
- h2o_cache_set(sock->ssl->handshake.client.session_cache, h2o_now(h2o_socket_get_loop(sock)),
- sock->ssl->handshake.client.session_cache_key, sock->ssl->handshake.client.session_cache_key_hash,
- h2o_iovec_init(session, 1));
- }
- }
-
- h2o_socket_cb handshake_cb = sock->ssl->handshake.cb;
- sock->_cb.write = NULL;
- sock->ssl->handshake.cb = NULL;
- if (err == NULL)
- decode_ssl_input(sock);
- handshake_cb(sock, err);
-}
-
-static void proceed_handshake(h2o_socket_t *sock, const char *err)
-{
- h2o_iovec_t first_input = {NULL};
- int ret = 0;
-
- sock->_cb.write = NULL;
-
- if (err != NULL) {
- goto Complete;
- }
-
- if (sock->ssl->ossl == NULL) {
-#if H2O_USE_PICOTLS
- /* prepare I/O */
- size_t consumed = sock->ssl->input.encrypted->size;
- ptls_buffer_t wbuf;
- ptls_buffer_init(&wbuf, "", 0);
-
- if (sock->ssl->ptls != NULL) {
- /* picotls in action, proceed the handshake */
- ret = ptls_handshake(sock->ssl->ptls, &wbuf, sock->ssl->input.encrypted->bytes, &consumed, NULL);
- } else {
- /* start using picotls if the first packet contains TLS 1.3 CH */
- ptls_context_t *ptls_ctx = h2o_socket_ssl_get_picotls_context(sock->ssl->ssl_ctx);
- if (ptls_ctx != NULL) {
- ptls_t *ptls = ptls_new(ptls_ctx, 1);
- if (ptls == NULL)
- h2o_fatal("no memory");
- ret = ptls_handshake(ptls, &wbuf, sock->ssl->input.encrypted->bytes, &consumed, NULL);
- if ((ret == 0 || ret == PTLS_ERROR_IN_PROGRESS) && wbuf.off != 0) {
- sock->ssl->ptls = ptls;
- sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_COMPLETE;
- } else {
- ptls_free(ptls);
- }
- }
- }
-
- if (sock->ssl->ptls != NULL) {
- /* complete I/O done by picotls */
- h2o_buffer_consume(&sock->ssl->input.encrypted, consumed);
- switch (ret) {
- case 0:
- case PTLS_ERROR_IN_PROGRESS:
- if (wbuf.off != 0) {
- h2o_socket_read_stop(sock);
- write_ssl_bytes(sock, wbuf.base, wbuf.off);
- flush_pending_ssl(sock, ret == 0 ? on_handshake_complete : proceed_handshake);
- } else {
- h2o_socket_read_start(sock, proceed_handshake);
- }
- break;
- default:
- /* FIXME send alert in wbuf before calling the callback */
- on_handshake_complete(sock, "picotls handshake error");
- break;
- }
- ptls_buffer_dispose(&wbuf);
- return;
- }
- ptls_buffer_dispose(&wbuf);
-#endif
-
- /* fallback to openssl if the attempt failed */
- create_ossl(sock);
- }
-
- if (sock->ssl->ossl != NULL && SSL_is_server(sock->ssl->ossl) &&
- sock->ssl->handshake.server.async_resumption.state == ASYNC_RESUMPTION_STATE_RECORD) {
- if (sock->ssl->input.encrypted->size <= 1024) {
- /* retain a copy of input if performing async resumption */
- first_input = h2o_iovec_init(alloca(sock->ssl->input.encrypted->size), sock->ssl->input.encrypted->size);
- memcpy(first_input.base, sock->ssl->input.encrypted->bytes, first_input.len);
- } else {
- sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_COMPLETE;
- }
- }
-
-Redo:
- ERR_clear_error();
- if (SSL_is_server(sock->ssl->ossl)) {
- ret = SSL_accept(sock->ssl->ossl);
- switch (sock->ssl->handshake.server.async_resumption.state) {
- case ASYNC_RESUMPTION_STATE_COMPLETE:
- break;
- case ASYNC_RESUMPTION_STATE_RECORD:
- /* async resumption has not been triggered; proceed the state to complete */
- sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_COMPLETE;
- break;
- case ASYNC_RESUMPTION_STATE_REQUEST_SENT: {
- /* sent async request, reset the ssl state, and wait for async response */
- assert(ret < 0);
- SSL_free(sock->ssl->ossl);
- create_ossl(sock);
- clear_output_buffer(sock->ssl);
- h2o_buffer_consume(&sock->ssl->input.encrypted, sock->ssl->input.encrypted->size);
- h2o_buffer_reserve(&sock->ssl->input.encrypted, first_input.len);
- memcpy(sock->ssl->input.encrypted->bytes, first_input.base, first_input.len);
- sock->ssl->input.encrypted->size = first_input.len;
- h2o_socket_read_stop(sock);
- return;
- }
- default:
- h2o_fatal("unexpected async resumption state");
- break;
- }
- } else {
- ret = SSL_connect(sock->ssl->ossl);
- }
-
- if (ret == 0 || (ret < 0 && SSL_get_error(sock->ssl->ossl, ret) != SSL_ERROR_WANT_READ)) {
- /* failed */
- long verify_result = SSL_get_verify_result(sock->ssl->ossl);
- if (verify_result != X509_V_OK) {
- err = X509_verify_cert_error_string(verify_result);
- } else {
- err = "ssl handshake failure";
- }
- goto Complete;
- }
-
- if (sock->ssl->output.bufs.size != 0) {
- h2o_socket_read_stop(sock);
- flush_pending_ssl(sock, ret == 1 ? on_handshake_complete : proceed_handshake);
- } else {
- if (ret == 1) {
- if (!SSL_is_server(sock->ssl->ossl)) {
- X509 *cert = SSL_get_peer_certificate(sock->ssl->ossl);
- if (cert != NULL) {
- switch (validate_hostname(sock->ssl->handshake.client.server_name, cert)) {
- case MatchFound:
- /* ok */
- break;
- case MatchNotFound:
- err = h2o_socket_error_ssl_cert_name_mismatch;
- break;
- default:
- err = h2o_socket_error_ssl_cert_invalid;
- break;
- }
- X509_free(cert);
- } else {
- err = h2o_socket_error_ssl_no_cert;
- }
- }
- goto Complete;
- }
- if (sock->ssl->input.encrypted->size != 0)
- goto Redo;
- h2o_socket_read_start(sock, proceed_handshake);
- }
- return;
-
-Complete:
- h2o_socket_read_stop(sock);
- on_handshake_complete(sock, err);
-}
-
-void h2o_socket_ssl_handshake(h2o_socket_t *sock, SSL_CTX *ssl_ctx, const char *server_name, h2o_socket_cb handshake_cb)
-{
- sock->ssl = h2o_mem_alloc(sizeof(*sock->ssl));
- memset(sock->ssl, 0, offsetof(struct st_h2o_socket_ssl_t, output.pool));
-
- sock->ssl->ssl_ctx = ssl_ctx;
-
- /* setup the buffers; sock->input should be empty, sock->ssl->input.encrypted should contain the initial input, if any */
- h2o_buffer_init(&sock->ssl->input.encrypted, &h2o_socket_buffer_prototype);
- if (sock->input->size != 0) {
- h2o_buffer_t *tmp = sock->input;
- sock->input = sock->ssl->input.encrypted;
- sock->ssl->input.encrypted = tmp;
- }
-
- h2o_mem_init_pool(&sock->ssl->output.pool);
-
- sock->ssl->handshake.cb = handshake_cb;
- if (server_name == NULL) {
- /* is server */
- if (SSL_CTX_sess_get_get_cb(sock->ssl->ssl_ctx) != NULL)
- sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_RECORD;
- if (sock->ssl->input.encrypted->size != 0)
- proceed_handshake(sock, 0);
- else
- h2o_socket_read_start(sock, proceed_handshake);
- } else {
- create_ossl(sock);
- h2o_cache_t *session_cache = h2o_socket_ssl_get_session_cache(sock->ssl->ssl_ctx);
- if (session_cache != NULL) {
- struct sockaddr_storage sa;
- int32_t port;
- if (h2o_socket_getpeername(sock, (struct sockaddr *)&sa) != 0 &&
- (port = h2o_socket_getport((struct sockaddr *)&sa)) != -1) {
- /* session cache is available */
- h2o_iovec_t session_cache_key;
- session_cache_key.base = h2o_mem_alloc(strlen(server_name) + sizeof(":" H2O_UINT16_LONGEST_STR));
- session_cache_key.len = sprintf(session_cache_key.base, "%s:%" PRIu16, server_name, (uint16_t)port);
- sock->ssl->handshake.client.session_cache = session_cache;
- sock->ssl->handshake.client.session_cache_key = session_cache_key;
- sock->ssl->handshake.client.session_cache_key_hash =
- h2o_cache_calchash(session_cache_key.base, session_cache_key.len);
-
- /* fetch from session cache */
- h2o_cache_ref_t *cacheref = h2o_cache_fetch(session_cache, h2o_now(h2o_socket_get_loop(sock)),
- sock->ssl->handshake.client.session_cache_key,
- sock->ssl->handshake.client.session_cache_key_hash);
- if (cacheref != NULL) {
- SSL_set_session(sock->ssl->ossl, (SSL_SESSION *)cacheref->value.base);
- h2o_cache_release(session_cache, cacheref);
- }
- }
- }
- sock->ssl->handshake.client.server_name = h2o_strdup(NULL, server_name, SIZE_MAX).base;
- SSL_set_tlsext_host_name(sock->ssl->ossl, sock->ssl->handshake.client.server_name);
- proceed_handshake(sock, 0);
- }
-}
-
-void h2o_socket_ssl_resume_server_handshake(h2o_socket_t *sock, h2o_iovec_t session_data)
-{
- if (session_data.len != 0) {
- const unsigned char *p = (void *)session_data.base;
- sock->ssl->handshake.server.async_resumption.session_data = d2i_SSL_SESSION(NULL, &p, (long)session_data.len);
- /* FIXME warn on failure */
- }
-
- sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_COMPLETE;
- proceed_handshake(sock, 0);
-
- if (sock->ssl->handshake.server.async_resumption.session_data != NULL) {
- SSL_SESSION_free(sock->ssl->handshake.server.async_resumption.session_data);
- sock->ssl->handshake.server.async_resumption.session_data = NULL;
- }
-}
-
-void h2o_socket_ssl_async_resumption_init(h2o_socket_ssl_resumption_get_async_cb get_async_cb,
- h2o_socket_ssl_resumption_new_cb new_cb)
-{
- resumption_get_async = get_async_cb;
- resumption_new = new_cb;
-}
-
-void h2o_socket_ssl_async_resumption_setup_ctx(SSL_CTX *ctx)
-{
- SSL_CTX_sess_set_get_cb(ctx, on_async_resumption_get);
- SSL_CTX_sess_set_new_cb(ctx, on_async_resumption_new);
- /* if necessary, it is the responsibility of the caller to disable the internal cache */
-}
-
-#if H2O_USE_PICOTLS
-
-static int get_ptls_index(void)
-{
- static int index = -1;
-
- if (index == -1) {
- static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- pthread_mutex_lock(&mutex);
- if (index == -1) {
- index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- assert(index != -1);
- }
- pthread_mutex_unlock(&mutex);
- }
-
- return index;
-}
-
-ptls_context_t *h2o_socket_ssl_get_picotls_context(SSL_CTX *ossl)
-{
- return SSL_CTX_get_ex_data(ossl, get_ptls_index());
-}
-
-void h2o_socket_ssl_set_picotls_context(SSL_CTX *ossl, ptls_context_t *ptls)
-{
- SSL_CTX_set_ex_data(ossl, get_ptls_index(), ptls);
-}
-
-#endif
-
-static void on_dispose_ssl_ctx_session_cache(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
-{
- h2o_cache_t *ssl_session_cache = (h2o_cache_t *)ptr;
- if (ssl_session_cache != NULL)
- h2o_cache_destroy(ssl_session_cache);
-}
-
-static int get_ssl_session_cache_index(void)
-{
- static int index = -1;
- static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- pthread_mutex_lock(&mutex);
- if (index == -1) {
- index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, on_dispose_ssl_ctx_session_cache);
- assert(index != -1);
- }
- pthread_mutex_unlock(&mutex);
- return index;
-}
-
-h2o_cache_t *h2o_socket_ssl_get_session_cache(SSL_CTX *ctx)
-{
- return (h2o_cache_t *)SSL_CTX_get_ex_data(ctx, get_ssl_session_cache_index());
-}
-
-void h2o_socket_ssl_set_session_cache(SSL_CTX *ctx, h2o_cache_t *cache)
-{
- SSL_CTX_set_ex_data(ctx, get_ssl_session_cache_index(), cache);
-}
-
-void h2o_socket_ssl_destroy_session_cache_entry(h2o_iovec_t value)
-{
- SSL_SESSION *session = (SSL_SESSION *)value.base;
- SSL_SESSION_free(session);
-}
-
-h2o_iovec_t h2o_socket_ssl_get_selected_protocol(h2o_socket_t *sock)
-{
- const unsigned char *data = NULL;
- unsigned len = 0;
-
- assert(sock->ssl != NULL);
-
-#if H2O_USE_PICOTLS
- if (sock->ssl->ptls != NULL) {
- const char *proto = ptls_get_negotiated_protocol(sock->ssl->ptls);
- return proto != NULL ? h2o_iovec_init(proto, strlen(proto)) : h2o_iovec_init(NULL, 0);
- }
-#endif
-
-#if H2O_USE_ALPN
- if (len == 0)
- SSL_get0_alpn_selected(sock->ssl->ossl, &data, &len);
-#endif
-#if H2O_USE_NPN
- if (len == 0)
- SSL_get0_next_proto_negotiated(sock->ssl->ossl, &data, &len);
-#endif
-
- return h2o_iovec_init(data, len);
-}
-
-static int on_alpn_select(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *_in, unsigned int inlen,
- void *_protocols)
-{
- const h2o_iovec_t *protocols = _protocols;
- size_t i;
-
- for (i = 0; protocols[i].len != 0; ++i) {
- const unsigned char *in = _in, *in_end = in + inlen;
- while (in != in_end) {
- size_t cand_len = *in++;
- if (in_end - in < cand_len) {
- /* broken request */
- return SSL_TLSEXT_ERR_NOACK;
- }
- if (cand_len == protocols[i].len && memcmp(in, protocols[i].base, cand_len) == 0) {
- goto Found;
- }
- in += cand_len;
- }
- }
- /* not found */
- return SSL_TLSEXT_ERR_NOACK;
-
-Found:
- *out = (const unsigned char *)protocols[i].base;
- *outlen = (unsigned char)protocols[i].len;
- return SSL_TLSEXT_ERR_OK;
-}
-
-#if H2O_USE_ALPN
-
-void h2o_ssl_register_alpn_protocols(SSL_CTX *ctx, const h2o_iovec_t *protocols)
-{
- SSL_CTX_set_alpn_select_cb(ctx, on_alpn_select, (void *)protocols);
-}
-
-#endif
-
-#if H2O_USE_NPN
-
-static int on_npn_advertise(SSL *ssl, const unsigned char **out, unsigned *outlen, void *protocols)
-{
- *out = protocols;
- *outlen = (unsigned)strlen(protocols);
- return SSL_TLSEXT_ERR_OK;
-}
-
-void h2o_ssl_register_npn_protocols(SSL_CTX *ctx, const char *protocols)
-{
- SSL_CTX_set_next_protos_advertised_cb(ctx, on_npn_advertise, (void *)protocols);
-}
-
-#endif
-
-void h2o_sliding_counter_stop(h2o_sliding_counter_t *counter, uint64_t now)
-{
- uint64_t elapsed;
-
- assert(counter->cur.start_at != 0);
-
- /* calculate the time used, and reset cur */
- if (now <= counter->cur.start_at)
- elapsed = 0;
- else
- elapsed = now - counter->cur.start_at;
- counter->cur.start_at = 0;
-
- /* adjust prev */
- counter->prev.sum += elapsed;
- counter->prev.sum -= counter->prev.slots[counter->prev.index];
- counter->prev.slots[counter->prev.index] = elapsed;
- if (++counter->prev.index >= sizeof(counter->prev.slots) / sizeof(counter->prev.slots[0]))
- counter->prev.index = 0;
-
- /* recalc average */
- counter->average = counter->prev.sum / (sizeof(counter->prev.slots) / sizeof(counter->prev.slots[0]));
-}
diff --git a/web/server/h2o/libh2o/lib/common/socket/evloop.c.h b/web/server/h2o/libh2o/lib/common/socket/evloop.c.h
deleted file mode 100644
index 754ed23b9..000000000
--- a/web/server/h2o/libh2o/lib/common/socket/evloop.c.h
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Fastly, Inc.
- *
- * 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 <netinet/in.h>
-#include <netinet/tcp.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include "cloexec.h"
-#include "h2o/linklist.h"
-
-#if !defined(H2O_USE_ACCEPT4)
-#ifdef __linux__
-#define H2O_USE_ACCEPT4 1
-#elif __FreeBSD__ >= 10
-#define H2O_USE_ACCEPT4 1
-#else
-#define H2O_USE_ACCEPT4 0
-#endif
-#endif
-
-struct st_h2o_evloop_socket_t {
- h2o_socket_t super;
- int fd;
- int _flags;
- h2o_evloop_t *loop;
- struct {
- size_t cnt;
- h2o_iovec_t *bufs;
- union {
- h2o_iovec_t *alloced_ptr;
- h2o_iovec_t smallbufs[4];
- };
- } _wreq;
- struct st_h2o_evloop_socket_t *_next_pending;
- struct st_h2o_evloop_socket_t *_next_statechanged;
-};
-
-static void link_to_pending(struct st_h2o_evloop_socket_t *sock);
-static void write_pending(struct st_h2o_evloop_socket_t *sock);
-static h2o_evloop_t *create_evloop(size_t sz);
-static void update_now(h2o_evloop_t *loop);
-static int32_t adjust_max_wait(h2o_evloop_t *loop, int32_t max_wait);
-
-/* functions to be defined in the backends */
-static int evloop_do_proceed(h2o_evloop_t *loop, int32_t max_wait);
-static void evloop_do_on_socket_create(struct st_h2o_evloop_socket_t *sock);
-static void evloop_do_on_socket_close(struct st_h2o_evloop_socket_t *sock);
-static void evloop_do_on_socket_export(struct st_h2o_evloop_socket_t *sock);
-
-#if H2O_USE_POLL || H2O_USE_EPOLL || H2O_USE_KQUEUE
-/* explicitly specified */
-#else
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
-#define H2O_USE_KQUEUE 1
-#elif defined(__linux)
-#define H2O_USE_EPOLL 1
-#else
-#define H2O_USE_POLL 1
-#endif
-#endif
-
-#if H2O_USE_POLL
-#include "evloop/poll.c.h"
-#elif H2O_USE_EPOLL
-#include "evloop/epoll.c.h"
-#elif H2O_USE_KQUEUE
-#include "evloop/kqueue.c.h"
-#else
-#error "poller not specified"
-#endif
-
-void link_to_pending(struct st_h2o_evloop_socket_t *sock)
-{
- if (sock->_next_pending == sock) {
- struct st_h2o_evloop_socket_t **slot = (sock->_flags & H2O_SOCKET_FLAG_IS_ACCEPTED_CONNECTION) != 0
- ? &sock->loop->_pending_as_server
- : &sock->loop->_pending_as_client;
- sock->_next_pending = *slot;
- *slot = sock;
- }
-}
-
-static void link_to_statechanged(struct st_h2o_evloop_socket_t *sock)
-{
- if (sock->_next_statechanged == sock) {
- sock->_next_statechanged = NULL;
- *sock->loop->_statechanged.tail_ref = sock;
- sock->loop->_statechanged.tail_ref = &sock->_next_statechanged;
- }
-}
-
-static const char *on_read_core(int fd, h2o_buffer_t **input)
-{
- int read_any = 0;
-
- while (1) {
- ssize_t rret;
- h2o_iovec_t buf = h2o_buffer_reserve(input, 4096);
- if (buf.base == NULL) {
- /* memory allocation failed */
- return h2o_socket_error_out_of_memory;
- }
- while ((rret = read(fd, buf.base, buf.len <= INT_MAX / 2 ? buf.len : INT_MAX / 2 + 1)) == -1 && errno == EINTR)
- ;
- if (rret == -1) {
- if (errno == EAGAIN)
- break;
- else
- return h2o_socket_error_io;
- } else if (rret == 0) {
- if (!read_any)
- return h2o_socket_error_closed; /* TODO notify close */
- break;
- }
- (*input)->size += rret;
- if (buf.len != rret)
- break;
- read_any = 1;
- }
- return NULL;
-}
-
-static void wreq_free_buffer_if_allocated(struct st_h2o_evloop_socket_t *sock)
-{
- if (sock->_wreq.smallbufs <= sock->_wreq.bufs &&
- sock->_wreq.bufs <= sock->_wreq.smallbufs + sizeof(sock->_wreq.smallbufs) / sizeof(sock->_wreq.smallbufs[0])) {
- /* no need to free */
- } else {
- free(sock->_wreq.alloced_ptr);
- sock->_wreq.bufs = sock->_wreq.smallbufs;
- }
-}
-
-static int write_core(int fd, h2o_iovec_t **bufs, size_t *bufcnt)
-{
- int iovcnt;
- ssize_t wret;
-
- if (*bufcnt != 0) {
- do {
- /* write */
- iovcnt = IOV_MAX;
- if (*bufcnt < iovcnt)
- iovcnt = (int)*bufcnt;
- while ((wret = writev(fd, (struct iovec *)*bufs, iovcnt)) == -1 && errno == EINTR)
- ;
- if (wret == -1) {
- if (errno != EAGAIN)
- return -1;
- break;
- }
- /* adjust the buffer */
- while ((*bufs)->len < wret) {
- wret -= (*bufs)->len;
- ++*bufs;
- --*bufcnt;
- assert(*bufcnt != 0);
- }
- if (((*bufs)->len -= wret) == 0) {
- ++*bufs;
- --*bufcnt;
- } else {
- (*bufs)->base += wret;
- }
- } while (*bufcnt != 0 && iovcnt == IOV_MAX);
- }
-
- return 0;
-}
-
-void write_pending(struct st_h2o_evloop_socket_t *sock)
-{
- assert(sock->super._cb.write != NULL);
-
- /* DONT_WRITE poll */
- if (sock->_wreq.cnt == 0)
- goto Complete;
-
- /* write */
- if (write_core(sock->fd, &sock->_wreq.bufs, &sock->_wreq.cnt) == 0 && sock->_wreq.cnt != 0) {
- /* partial write */
- return;
- }
-
- /* either completed or failed */
- wreq_free_buffer_if_allocated(sock);
-
-Complete:
- sock->_flags |= H2O_SOCKET_FLAG_IS_WRITE_NOTIFY;
- link_to_pending(sock);
- link_to_statechanged(sock); /* might need to disable the write polling */
-}
-
-static void read_on_ready(struct st_h2o_evloop_socket_t *sock)
-{
- const char *err = 0;
- size_t prev_bytes_read = sock->super.input->size;
-
- if ((sock->_flags & H2O_SOCKET_FLAG_DONT_READ) != 0)
- goto Notify;
-
- if ((err = on_read_core(sock->fd, sock->super.ssl == NULL ? &sock->super.input : &sock->super.ssl->input.encrypted)) != NULL)
- goto Notify;
-
- if (sock->super.ssl != NULL && sock->super.ssl->handshake.cb == NULL)
- err = decode_ssl_input(&sock->super);
-
-Notify:
- /* the application may get notified even if no new data is avaiable. The
- * behavior is intentional; it is designed as such so that the applications
- * can update their timeout counters when a partial SSL record arrives.
- */
- sock->super.bytes_read = sock->super.input->size - prev_bytes_read;
- sock->super._cb.read(&sock->super, err);
-}
-
-void do_dispose_socket(h2o_socket_t *_sock)
-{
- struct st_h2o_evloop_socket_t *sock = (struct st_h2o_evloop_socket_t *)_sock;
-
- evloop_do_on_socket_close(sock);
- wreq_free_buffer_if_allocated(sock);
- if (sock->fd != -1) {
- close(sock->fd);
- sock->fd = -1;
- }
- sock->_flags = H2O_SOCKET_FLAG_IS_DISPOSED;
- link_to_statechanged(sock);
-}
-
-void do_write(h2o_socket_t *_sock, h2o_iovec_t *_bufs, size_t bufcnt, h2o_socket_cb cb)
-{
- struct st_h2o_evloop_socket_t *sock = (struct st_h2o_evloop_socket_t *)_sock;
- h2o_iovec_t *bufs;
- h2o_iovec_t *tofree = NULL;
-
- assert(sock->super._cb.write == NULL);
- assert(sock->_wreq.cnt == 0);
- sock->super._cb.write = cb;
-
- /* cap the number of buffers, since we're using alloca */
- if (bufcnt > 10000)
- bufs = tofree = h2o_mem_alloc(sizeof(*bufs) * bufcnt);
- else
- bufs = alloca(sizeof(*bufs) * bufcnt);
-
- memcpy(bufs, _bufs, sizeof(*bufs) * bufcnt);
-
- /* try to write now */
- if (write_core(sock->fd, &bufs, &bufcnt) != 0) {
- /* fill in _wreq.bufs with fake data to indicate error */
- sock->_wreq.bufs = sock->_wreq.smallbufs;
- sock->_wreq.cnt = 1;
- *sock->_wreq.bufs = h2o_iovec_init(H2O_STRLIT("deadbeef"));
- sock->_flags |= H2O_SOCKET_FLAG_IS_WRITE_NOTIFY;
- link_to_pending(sock);
- goto Out;
- }
- if (bufcnt == 0) {
- /* write complete, schedule the callback */
- sock->_flags |= H2O_SOCKET_FLAG_IS_WRITE_NOTIFY;
- link_to_pending(sock);
- goto Out;
- }
-
-
- /* setup the buffer to send pending data */
- if (bufcnt <= sizeof(sock->_wreq.smallbufs) / sizeof(sock->_wreq.smallbufs[0])) {
- sock->_wreq.bufs = sock->_wreq.smallbufs;
- } else {
- sock->_wreq.bufs = h2o_mem_alloc(sizeof(h2o_iovec_t) * bufcnt);
- sock->_wreq.alloced_ptr = sock->_wreq.bufs;
- }
- memcpy(sock->_wreq.bufs, bufs, sizeof(h2o_iovec_t) * bufcnt);
- sock->_wreq.cnt = bufcnt;
-
- /* schedule the write */
- link_to_statechanged(sock);
-Out:
- free(tofree);
-}
-
-int h2o_socket_get_fd(h2o_socket_t *_sock)
-{
- struct st_h2o_evloop_socket_t *sock = (struct st_h2o_evloop_socket_t *)_sock;
- return sock->fd;
-}
-
-void do_read_start(h2o_socket_t *_sock)
-{
- struct st_h2o_evloop_socket_t *sock = (struct st_h2o_evloop_socket_t *)_sock;
-
- link_to_statechanged(sock);
-}
-
-void do_read_stop(h2o_socket_t *_sock)
-{
- struct st_h2o_evloop_socket_t *sock = (struct st_h2o_evloop_socket_t *)_sock;
-
- sock->_flags &= ~H2O_SOCKET_FLAG_IS_READ_READY;
- link_to_statechanged(sock);
-}
-
-void h2o_socket_dont_read(h2o_socket_t *_sock, int dont_read)
-{
- struct st_h2o_evloop_socket_t *sock = (struct st_h2o_evloop_socket_t *)_sock;
-
- if (dont_read) {
- sock->_flags |= H2O_SOCKET_FLAG_DONT_READ;
- } else {
- sock->_flags &= ~H2O_SOCKET_FLAG_DONT_READ;
- }
-}
-
-int do_export(h2o_socket_t *_sock, h2o_socket_export_t *info)
-{
- struct st_h2o_evloop_socket_t *sock = (void *)_sock;
-
- assert((sock->_flags & H2O_SOCKET_FLAG_IS_DISPOSED) == 0);
- evloop_do_on_socket_export(sock);
- sock->_flags = H2O_SOCKET_FLAG_IS_DISPOSED;
-
- info->fd = sock->fd;
- sock->fd = -1;
-
- return 0;
-}
-
-h2o_socket_t *do_import(h2o_loop_t *loop, h2o_socket_export_t *info)
-{
- return h2o_evloop_socket_create(loop, info->fd, 0);
-}
-
-h2o_loop_t *h2o_socket_get_loop(h2o_socket_t *_sock)
-{
- struct st_h2o_evloop_socket_t *sock = (void *)_sock;
- return sock->loop;
-}
-
-socklen_t h2o_socket_getsockname(h2o_socket_t *_sock, struct sockaddr *sa)
-{
- struct st_h2o_evloop_socket_t *sock = (void *)_sock;
- socklen_t len = sizeof(struct sockaddr_storage);
- if (getsockname(sock->fd, sa, &len) != 0)
- return 0;
- return len;
-}
-
-socklen_t get_peername_uncached(h2o_socket_t *_sock, struct sockaddr *sa)
-{
- struct st_h2o_evloop_socket_t *sock = (void *)_sock;
- socklen_t len = sizeof(struct sockaddr_storage);
- if (getpeername(sock->fd, sa, &len) != 0)
- return 0;
- return len;
-}
-
-static struct st_h2o_evloop_socket_t *create_socket(h2o_evloop_t *loop, int fd, int flags)
-{
- struct st_h2o_evloop_socket_t *sock;
-
- fcntl(fd, F_SETFL, O_NONBLOCK);
-
- sock = h2o_mem_alloc(sizeof(*sock));
- memset(sock, 0, sizeof(*sock));
- h2o_buffer_init(&sock->super.input, &h2o_socket_buffer_prototype);
- sock->loop = loop;
- sock->fd = fd;
- sock->_flags = flags;
- sock->_wreq.bufs = sock->_wreq.smallbufs;
- sock->_next_pending = sock;
- sock->_next_statechanged = sock;
-
- evloop_do_on_socket_create(sock);
-
- return sock;
-}
-
-static struct st_h2o_evloop_socket_t *create_socket_set_nodelay(h2o_evloop_t *loop, int fd, int flags)
-{
- int on = 1;
- setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
- return create_socket(loop, fd, flags);
-}
-
-h2o_socket_t *h2o_evloop_socket_create(h2o_evloop_t *loop, int fd, int flags)
-{
- fcntl(fd, F_SETFL, O_NONBLOCK);
- return &create_socket(loop, fd, flags)->super;
-}
-
-h2o_socket_t *h2o_evloop_socket_accept(h2o_socket_t *_listener)
-{
- struct st_h2o_evloop_socket_t *listener = (struct st_h2o_evloop_socket_t *)_listener;
- int fd;
-
-#if H2O_USE_ACCEPT4
- if ((fd = accept4(listener->fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC)) == -1)
- return NULL;
-#else
- if ((fd = cloexec_accept(listener->fd, NULL, NULL)) == -1)
- return NULL;
- fcntl(fd, F_SETFL, O_NONBLOCK);
-#endif
-
- return &create_socket_set_nodelay(listener->loop, fd, H2O_SOCKET_FLAG_IS_ACCEPTED_CONNECTION)->super;
-}
-
-h2o_socket_t *h2o_socket_connect(h2o_loop_t *loop, struct sockaddr *addr, socklen_t addrlen, h2o_socket_cb cb)
-{
- int fd;
- struct st_h2o_evloop_socket_t *sock;
-
- if ((fd = cloexec_socket(addr->sa_family, SOCK_STREAM, 0)) == -1)
- return NULL;
- fcntl(fd, F_SETFL, O_NONBLOCK);
- if (!(connect(fd, addr, addrlen) == 0 || errno == EINPROGRESS)) {
- close(fd);
- return NULL;
- }
-
- sock = create_socket_set_nodelay(loop, fd, H2O_SOCKET_FLAG_IS_CONNECTING);
- h2o_socket_notify_write(&sock->super, cb);
- return &sock->super;
-}
-
-h2o_evloop_t *create_evloop(size_t sz)
-{
- h2o_evloop_t *loop = h2o_mem_alloc(sz);
-
- memset(loop, 0, sz);
- loop->_statechanged.tail_ref = &loop->_statechanged.head;
- h2o_linklist_init_anchor(&loop->_timeouts);
-
- update_now(loop);
-
- return loop;
-}
-
-void update_now(h2o_evloop_t *loop)
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- loop->_now = (uint64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
-}
-
-int32_t adjust_max_wait(h2o_evloop_t *loop, int32_t max_wait)
-{
- uint64_t wake_at = h2o_timeout_get_wake_at(&loop->_timeouts);
-
- update_now(loop);
-
- if (wake_at <= loop->_now) {
- max_wait = 0;
- } else {
- uint64_t delta = wake_at - loop->_now;
- if (delta < max_wait)
- max_wait = (int32_t)delta;
- }
-
- return max_wait;
-}
-
-void h2o_socket_notify_write(h2o_socket_t *_sock, h2o_socket_cb cb)
-{
- struct st_h2o_evloop_socket_t *sock = (struct st_h2o_evloop_socket_t *)_sock;
- assert(sock->super._cb.write == NULL);
- assert(sock->_wreq.cnt == 0);
-
- sock->super._cb.write = cb;
- link_to_statechanged(sock);
-}
-
-static void run_socket(struct st_h2o_evloop_socket_t *sock)
-{
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_DISPOSED) != 0) {
- /* is freed in updatestates phase */
- return;
- }
-
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_READ_READY) != 0) {
- sock->_flags &= ~H2O_SOCKET_FLAG_IS_READ_READY;
- read_on_ready(sock);
- }
-
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_WRITE_NOTIFY) != 0) {
- const char *err = NULL;
- assert(sock->super._cb.write != NULL);
- sock->_flags &= ~H2O_SOCKET_FLAG_IS_WRITE_NOTIFY;
- if (sock->_wreq.cnt != 0) {
- /* error */
- err = h2o_socket_error_io;
- sock->_wreq.cnt = 0;
- } else if ((sock->_flags & H2O_SOCKET_FLAG_IS_CONNECTING) != 0) {
- sock->_flags &= ~H2O_SOCKET_FLAG_IS_CONNECTING;
- int so_err = 0;
- socklen_t l = sizeof(so_err);
- so_err = 0;
- if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &so_err, &l) != 0 || so_err != 0) {
- /* FIXME lookup the error table */
- err = h2o_socket_error_conn_fail;
- }
- }
- on_write_complete(&sock->super, err);
- }
-}
-
-static void run_pending(h2o_evloop_t *loop)
-{
- struct st_h2o_evloop_socket_t *sock;
-
- while (loop->_pending_as_server != NULL || loop->_pending_as_client != NULL) {
- while ((sock = loop->_pending_as_client) != NULL) {
- loop->_pending_as_client = sock->_next_pending;
- sock->_next_pending = sock;
- run_socket(sock);
- }
- if ((sock = loop->_pending_as_server) != NULL) {
- loop->_pending_as_server = sock->_next_pending;
- sock->_next_pending = sock;
- run_socket(sock);
- }
- }
-}
-
-void h2o_evloop_destroy(h2o_evloop_t *loop)
-{
- struct st_h2o_evloop_socket_t *sock;
-
- /* timeouts are governed by the application and MUST be destroyed prior to destroying the loop */
- assert(h2o_linklist_is_empty(&loop->_timeouts));
-
- /* dispose all socket */
- while ((sock = loop->_pending_as_client) != NULL) {
- loop->_pending_as_client = sock->_next_pending;
- sock->_next_pending = sock;
- h2o_socket_close((h2o_socket_t *)sock);
- }
- while ((sock = loop->_pending_as_server) != NULL) {
- loop->_pending_as_server = sock->_next_pending;
- sock->_next_pending = sock;
- h2o_socket_close((h2o_socket_t *)sock);
- }
-
- /* now all socket are disposedand and placed in linked list statechanged
- * we can freeing memory in cycle by next_statechanged,
- */
- while ((sock = loop->_statechanged.head) != NULL) {
- loop->_statechanged.head = sock->_next_statechanged;
- free(sock);
- }
-
- /* lastly we need to free loop memory */
- free(loop);
-}
-
-int h2o_evloop_run(h2o_evloop_t *loop, int32_t max_wait)
-{
- h2o_linklist_t *node;
-
- /* update socket states, poll, set readable flags, perform pending writes */
- if (evloop_do_proceed(loop, max_wait) != 0)
- return -1;
-
- /* run the pending callbacks */
- run_pending(loop);
-
- /* run the timeouts */
- for (node = loop->_timeouts.next; node != &loop->_timeouts; node = node->next) {
- h2o_timeout_t *timeout = H2O_STRUCT_FROM_MEMBER(h2o_timeout_t, _link, node);
- h2o_timeout_run(loop, timeout, loop->_now);
- }
- /* assert h2o_timeout_run has called run_pending */
- assert(loop->_pending_as_client == NULL);
- assert(loop->_pending_as_server == NULL);
-
- if (h2o_sliding_counter_is_running(&loop->exec_time_counter)) {
- update_now(loop);
- h2o_sliding_counter_stop(&loop->exec_time_counter, loop->_now);
- }
-
- return 0;
-}
-
-void h2o_timeout__do_init(h2o_evloop_t *loop, h2o_timeout_t *timeout)
-{
- h2o_linklist_insert(&loop->_timeouts, &timeout->_link);
-}
-
-void h2o_timeout__do_dispose(h2o_evloop_t *loop, h2o_timeout_t *timeout)
-{
- h2o_linklist_unlink(&timeout->_link);
-}
-
-void h2o_timeout__do_link(h2o_evloop_t *loop, h2o_timeout_t *timeout, h2o_timeout_entry_t *entry)
-{
- /* nothing to do */
-}
-
-void h2o_timeout__do_post_callback(h2o_evloop_t *loop)
-{
- run_pending(loop);
-}
diff --git a/web/server/h2o/libh2o/lib/common/socket/evloop/epoll.c.h b/web/server/h2o/libh2o/lib/common/socket/evloop/epoll.c.h
deleted file mode 100644
index 247dac893..000000000
--- a/web/server/h2o/libh2o/lib/common/socket/evloop/epoll.c.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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 <assert.h>
-#include <limits.h>
-#include <stdio.h>
-#include <sys/epoll.h>
-
-#if 0
-#define DEBUG_LOG(...) fprintf(stderr, __VA_ARGS__)
-#else
-#define DEBUG_LOG(...)
-#endif
-
-struct st_h2o_evloop_epoll_t {
- h2o_evloop_t super;
- int ep;
-};
-
-static int update_status(struct st_h2o_evloop_epoll_t *loop)
-{
- while (loop->super._statechanged.head != NULL) {
- /* detach the top */
- struct st_h2o_evloop_socket_t *sock = loop->super._statechanged.head;
- loop->super._statechanged.head = sock->_next_statechanged;
- sock->_next_statechanged = sock;
- /* update the state */
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_DISPOSED) != 0) {
- free(sock);
- } else {
- int changed = 0, op, ret;
- struct epoll_event ev;
- ev.events = 0;
- if (h2o_socket_is_reading(&sock->super)) {
- ev.events |= EPOLLIN;
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_READ) == 0) {
- sock->_flags |= H2O_SOCKET_FLAG_IS_POLLED_FOR_READ;
- changed = 1;
- }
- } else {
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_READ) != 0) {
- sock->_flags &= ~H2O_SOCKET_FLAG_IS_POLLED_FOR_READ;
- changed = 1;
- }
- }
- if (h2o_socket_is_writing(&sock->super)) {
- ev.events |= EPOLLOUT;
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE) == 0) {
- sock->_flags |= H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE;
- changed = 1;
- }
- } else {
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE) != 0) {
- sock->_flags &= ~H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE;
- changed = 1;
- }
- }
- if (changed) {
- if ((sock->_flags & H2O_SOCKET_FLAG__EPOLL_IS_REGISTERED) != 0) {
- if (ev.events != 0)
- op = EPOLL_CTL_MOD;
- else
- op = EPOLL_CTL_DEL;
- } else {
- assert(ev.events != 0);
- op = EPOLL_CTL_ADD;
- }
- ev.data.ptr = sock;
- while ((ret = epoll_ctl(loop->ep, op, sock->fd, &ev)) != 0 && errno == EINTR)
- ;
- if (ret != 0)
- return -1;
- if (op == EPOLL_CTL_DEL)
- sock->_flags &= ~H2O_SOCKET_FLAG__EPOLL_IS_REGISTERED;
- else
- sock->_flags |= H2O_SOCKET_FLAG__EPOLL_IS_REGISTERED;
- }
- }
- }
- loop->super._statechanged.tail_ref = &loop->super._statechanged.head;
-
- return 0;
-}
-
-int evloop_do_proceed(h2o_evloop_t *_loop, int32_t max_wait)
-{
- struct st_h2o_evloop_epoll_t *loop = (struct st_h2o_evloop_epoll_t *)_loop;
- struct epoll_event events[256];
- int nevents, i;
-
- /* collect (and update) status */
- if (update_status(loop) != 0)
- return -1;
-
- /* poll */
- max_wait = adjust_max_wait(&loop->super, max_wait);
- nevents = epoll_wait(loop->ep, events, sizeof(events) / sizeof(events[0]), max_wait);
- update_now(&loop->super);
- if (nevents == -1)
- return -1;
-
- if (nevents != 0)
- h2o_sliding_counter_start(&loop->super.exec_time_counter, loop->super._now);
-
- /* update readable flags, perform writes */
- for (i = 0; i != nevents; ++i) {
- struct st_h2o_evloop_socket_t *sock = events[i].data.ptr;
- int notified = 0;
- if ((events[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR)) != 0) {
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_READ) != 0) {
- sock->_flags |= H2O_SOCKET_FLAG_IS_READ_READY;
- link_to_pending(sock);
- notified = 1;
- }
- }
- if ((events[i].events & (EPOLLOUT | EPOLLHUP | EPOLLERR)) != 0) {
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE) != 0) {
- write_pending(sock);
- notified = 1;
- }
- }
- if (!notified) {
- static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
- static time_t last_reported = 0;
- time_t now = time(NULL);
- pthread_mutex_lock(&lock);
- if (last_reported + 60 < now) {
- last_reported = now;
- fprintf(stderr, "ignoring epoll event (fd:%d,event:%x)\n", sock->fd, (int)events[i].events);
- }
- pthread_mutex_unlock(&lock);
- }
- }
-
- return 0;
-}
-
-static void evloop_do_on_socket_create(struct st_h2o_evloop_socket_t *sock)
-{
-}
-
-static void evloop_do_on_socket_close(struct st_h2o_evloop_socket_t *sock)
-{
- struct st_h2o_evloop_epoll_t *loop = (void *)sock->loop;
- int ret;
-
- if (sock->fd == -1)
- return;
- if ((sock->_flags & H2O_SOCKET_FLAG__EPOLL_IS_REGISTERED) == 0)
- return;
- while ((ret = epoll_ctl(loop->ep, EPOLL_CTL_DEL, sock->fd, NULL)) != 0 && errno == EINTR)
- ;
- if (ret != 0)
- fprintf(stderr, "socket_close: epoll(DEL) returned error %d (fd=%d)\n", errno, sock->fd);
-}
-
-static void evloop_do_on_socket_export(struct st_h2o_evloop_socket_t *sock)
-{
- struct st_h2o_evloop_epoll_t *loop = (void *)sock->loop;
- int ret;
-
- if ((sock->_flags & H2O_SOCKET_FLAG__EPOLL_IS_REGISTERED) == 0)
- return;
- while ((ret = epoll_ctl(loop->ep, EPOLL_CTL_DEL, sock->fd, NULL)) != 0 && errno == EINTR)
- ;
- if (ret != 0)
- fprintf(stderr, "socket_export: epoll(DEL) returned error %d (fd=%d)\n", errno, sock->fd);
-}
-
-h2o_evloop_t *h2o_evloop_create(void)
-{
- struct st_h2o_evloop_epoll_t *loop = (struct st_h2o_evloop_epoll_t *)create_evloop(sizeof(*loop));
-
- pthread_mutex_lock(&cloexec_mutex);
- loop->ep = epoll_create(10);
- while (fcntl(loop->ep, F_SETFD, FD_CLOEXEC) == -1) {
- if (errno != EAGAIN) {
- fprintf(stderr, "h2o_evloop_create: failed to set FD_CLOEXEC to the epoll fd (errno=%d)\n", errno);
- abort();
- }
- }
- pthread_mutex_unlock(&cloexec_mutex);
-
- return &loop->super;
-}
diff --git a/web/server/h2o/libh2o/lib/common/socket/evloop/kqueue.c.h b/web/server/h2o/libh2o/lib/common/socket/evloop/kqueue.c.h
deleted file mode 100644
index 21288ed7c..000000000
--- a/web/server/h2o/libh2o/lib/common/socket/evloop/kqueue.c.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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 <assert.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/event.h>
-#include <sys/time.h>
-
-#if 0
-#define DEBUG_LOG(...) fprintf(stderr, __VA_ARGS__)
-#else
-#define DEBUG_LOG(...)
-#endif
-
-struct st_h2o_socket_loop_kqueue_t {
- h2o_evloop_t super;
- int kq;
-};
-
-static void ev_set(struct kevent *ev, int fd, int filter, int flags, struct st_h2o_evloop_socket_t *sock)
-{
-#ifdef __NetBSD__
- EV_SET(ev, fd, filter, flags, 0, 0, (intptr_t)sock);
-#else
- EV_SET(ev, fd, filter, flags, 0, 0, sock);
-#endif
-}
-
-static int collect_status(struct st_h2o_socket_loop_kqueue_t *loop, struct kevent *changelist, int changelist_capacity)
-{
- int change_index = 0;
-
-#define SET_AND_UPDATE(filter, flags) \
- do { \
- ev_set(changelist + change_index++, sock->fd, filter, flags, sock); \
- if (change_index == changelist_capacity) { \
- int ret; \
- while ((ret = kevent(loop->kq, changelist, change_index, NULL, 0, NULL)) != 0 && errno == EINTR) \
- ; \
- if (ret == -1) \
- return -1; \
- change_index = 0; \
- } \
- } while (0)
-
- while (loop->super._statechanged.head != NULL) {
- /* detach the top */
- struct st_h2o_evloop_socket_t *sock = loop->super._statechanged.head;
- loop->super._statechanged.head = sock->_next_statechanged;
- sock->_next_statechanged = sock;
- /* update the state */
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_DISPOSED) != 0) {
- free(sock);
- } else {
- if (h2o_socket_is_reading(&sock->super)) {
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_READ) == 0) {
- sock->_flags |= H2O_SOCKET_FLAG_IS_POLLED_FOR_READ;
- SET_AND_UPDATE(EVFILT_READ, EV_ADD);
- }
- } else {
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_READ) != 0) {
- sock->_flags &= ~H2O_SOCKET_FLAG_IS_POLLED_FOR_READ;
- SET_AND_UPDATE(EVFILT_READ, EV_DELETE);
- }
- }
- if (h2o_socket_is_writing(&sock->super)) {
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE) == 0) {
- sock->_flags |= H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE;
- SET_AND_UPDATE(EVFILT_WRITE, EV_ADD);
- }
- } else {
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE) != 0) {
- sock->_flags &= ~H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE;
- SET_AND_UPDATE(EVFILT_WRITE, EV_DELETE);
- }
- }
- }
- }
- loop->super._statechanged.tail_ref = &loop->super._statechanged.head;
-
- return change_index;
-
-#undef SET_AND_UPDATE
-}
-
-int evloop_do_proceed(h2o_evloop_t *_loop, int32_t max_wait)
-{
- struct st_h2o_socket_loop_kqueue_t *loop = (struct st_h2o_socket_loop_kqueue_t *)_loop;
- struct kevent changelist[64], events[128];
- int nchanges, nevents, i;
- struct timespec ts;
-
- /* collect (and update) status */
- if ((nchanges = collect_status(loop, changelist, sizeof(changelist) / sizeof(changelist[0]))) == -1)
- return -1;
-
- /* poll */
- max_wait = adjust_max_wait(&loop->super, max_wait);
- ts.tv_sec = max_wait / 1000;
- ts.tv_nsec = max_wait % 1000 * 1000 * 1000;
- nevents = kevent(loop->kq, changelist, nchanges, events, sizeof(events) / sizeof(events[0]), &ts);
-
- update_now(&loop->super);
- if (nevents == -1)
- return -1;
-
- if (nevents != 0)
- h2o_sliding_counter_start(&loop->super.exec_time_counter, loop->super._now);
-
- /* update readable flags, perform writes */
- for (i = 0; i != nevents; ++i) {
- struct st_h2o_evloop_socket_t *sock = (void *)events[i].udata;
- assert(sock->fd == events[i].ident);
- switch (events[i].filter) {
- case EVFILT_READ:
- if (sock->_flags != H2O_SOCKET_FLAG_IS_DISPOSED) {
- sock->_flags |= H2O_SOCKET_FLAG_IS_READ_READY;
- link_to_pending(sock);
- }
- break;
- case EVFILT_WRITE:
- if (sock->_flags != H2O_SOCKET_FLAG_IS_DISPOSED) {
- write_pending(sock);
- }
- break;
- default:
- break; /* ??? */
- }
- }
-
- return 0;
-}
-
-static void evloop_do_on_socket_create(struct st_h2o_evloop_socket_t *sock)
-{
-}
-
-static void evloop_do_on_socket_close(struct st_h2o_evloop_socket_t *sock)
-{
-}
-
-static void evloop_do_on_socket_export(struct st_h2o_evloop_socket_t *sock)
-{
- struct st_h2o_socket_loop_kqueue_t *loop = (void *)sock->loop;
- struct kevent changelist[2];
- int change_index = 0, ret;
-
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_READ) != 0)
- ev_set(changelist + change_index++, sock->fd, EVFILT_READ, EV_DELETE, 0);
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE) != 0)
- ev_set(changelist + change_index++, sock->fd, EVFILT_WRITE, EV_DELETE, 0);
- if (change_index == 0)
- return;
- while ((ret = kevent(loop->kq, changelist, change_index, NULL, 0, NULL)) != 0 && errno == EINTR)
- ;
- if (ret == -1)
- fprintf(stderr, "kevent returned error %d (fd=%d)", errno, sock->fd);
-}
-
-h2o_evloop_t *h2o_evloop_create(void)
-{
- struct st_h2o_socket_loop_kqueue_t *loop = (struct st_h2o_socket_loop_kqueue_t *)create_evloop(sizeof(*loop));
-
- loop->kq = kqueue();
-
- return &loop->super;
-}
diff --git a/web/server/h2o/libh2o/lib/common/socket/evloop/poll.c.h b/web/server/h2o/libh2o/lib/common/socket/evloop/poll.c.h
deleted file mode 100644
index 8b3f3d149..000000000
--- a/web/server/h2o/libh2o/lib/common/socket/evloop/poll.c.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2014,2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <stdio.h>
-#include <poll.h>
-
-#if 0
-#define DEBUG_LOG(...) fprintf(stderr, __VA_ARGS__)
-#else
-#define DEBUG_LOG(...)
-#endif
-
-struct st_h2o_evloop_poll_t {
- h2o_evloop_t super;
- H2O_VECTOR(struct st_h2o_evloop_socket_t *) socks;
-};
-
-static void update_socks(struct st_h2o_evloop_poll_t *loop)
-{
- /* update loop->socks */
- while (loop->super._statechanged.head != NULL) {
- /* detach the top */
- struct st_h2o_evloop_socket_t *sock = loop->super._statechanged.head;
- loop->super._statechanged.head = sock->_next_statechanged;
- sock->_next_statechanged = sock;
- /* update the state */
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_DISPOSED) != 0) {
- assert(sock->fd == -1);
- free(sock);
- } else {
- assert(sock->fd < loop->socks.size);
- if (loop->socks.entries[sock->fd] == NULL) {
- loop->socks.entries[sock->fd] = sock;
- } else {
- assert(loop->socks.entries[sock->fd] == sock);
- }
- if (h2o_socket_is_reading(&sock->super)) {
- DEBUG_LOG("setting READ for fd: %d\n", sock->fd);
- sock->_flags |= H2O_SOCKET_FLAG_IS_POLLED_FOR_READ;
- } else {
- DEBUG_LOG("clearing READ for fd: %d\n", sock->fd);
- sock->_flags &= ~H2O_SOCKET_FLAG_IS_POLLED_FOR_READ;
- }
- if (h2o_socket_is_writing(&sock->super)) {
- DEBUG_LOG("setting WRITE for fd: %d\n", sock->fd);
- sock->_flags |= H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE;
- } else {
- DEBUG_LOG("clearing WRITE for fd: %d\n", sock->fd);
- sock->_flags &= ~H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE;
- }
- }
- }
- loop->super._statechanged.tail_ref = &loop->super._statechanged.head;
-}
-
-int evloop_do_proceed(h2o_evloop_t *_loop, int32_t max_wait)
-{
- struct st_h2o_evloop_poll_t *loop = (struct st_h2o_evloop_poll_t *)_loop;
- H2O_VECTOR(struct pollfd) pollfds = {NULL};
- int fd, ret;
-
- /* update status */
- update_socks(loop);
-
- /* build list of fds to be polled */
- for (fd = 0; fd != loop->socks.size; ++fd) {
- struct st_h2o_evloop_socket_t *sock = loop->socks.entries[fd];
- if (sock == NULL)
- continue;
- assert(fd == sock->fd);
- if ((sock->_flags & (H2O_SOCKET_FLAG_IS_POLLED_FOR_READ | H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE)) != 0) {
- h2o_vector_reserve(NULL, &pollfds, pollfds.size + 1);
- struct pollfd *slot = pollfds.entries + pollfds.size++;
- slot->fd = fd;
- slot->events = 0;
- slot->revents = 0;
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_READ) != 0)
- slot->events |= POLLIN;
- if ((sock->_flags & H2O_SOCKET_FLAG_IS_POLLED_FOR_WRITE) != 0)
- slot->events |= POLLOUT;
- }
- }
-
- /* call */
- max_wait = adjust_max_wait(&loop->super, max_wait);
- ret = poll(pollfds.entries, (nfds_t)pollfds.size, max_wait);
- update_now(&loop->super);
- if (ret == -1)
- goto Exit;
- DEBUG_LOG("poll returned: %d\n", ret);
-
- /* update readable flags, perform writes */
- if (ret > 0) {
- size_t i;
- h2o_sliding_counter_start(&loop->super.exec_time_counter, loop->super._now);
- for (i = 0; i != pollfds.size; ++i) {
- /* set read_ready flag before calling the write cb, since app. code invoked by the latter may close the socket, clearing
- * the former flag */
- if ((pollfds.entries[i].revents & POLLIN) != 0) {
- struct st_h2o_evloop_socket_t *sock = loop->socks.entries[pollfds.entries[i].fd];
- assert(sock != NULL);
- assert(sock->fd == pollfds.entries[i].fd);
- if (sock->_flags != H2O_SOCKET_FLAG_IS_DISPOSED) {
- sock->_flags |= H2O_SOCKET_FLAG_IS_READ_READY;
- link_to_pending(sock);
- DEBUG_LOG("added fd %d as read_ready\n", sock->fd);
- }
- }
- if ((pollfds.entries[i].revents & POLLOUT) != 0) {
- struct st_h2o_evloop_socket_t *sock = loop->socks.entries[pollfds.entries[i].fd];
- assert(sock != NULL);
- assert(sock->fd == pollfds.entries[i].fd);
- if (sock->_flags != H2O_SOCKET_FLAG_IS_DISPOSED) {
- DEBUG_LOG("handling pending writes on fd %d\n", fd);
- write_pending(sock);
- }
- }
- }
- ret = 0;
- }
-
-Exit:
- free(pollfds.entries);
- return ret;
-}
-
-static void evloop_do_on_socket_create(struct st_h2o_evloop_socket_t *sock)
-{
- struct st_h2o_evloop_poll_t *loop = (struct st_h2o_evloop_poll_t *)sock->loop;
-
- if (sock->fd >= loop->socks.size) {
- h2o_vector_reserve(NULL, &loop->socks, sock->fd + 1);
- memset(loop->socks.entries + loop->socks.size, 0, (sock->fd + 1 - loop->socks.size) * sizeof(loop->socks.entries[0]));
- loop->socks.size = sock->fd + 1;
- }
-
- if (loop->socks.entries[sock->fd] != NULL)
- assert(loop->socks.entries[sock->fd]->_flags == H2O_SOCKET_FLAG_IS_DISPOSED);
-}
-
-static void evloop_do_on_socket_close(struct st_h2o_evloop_socket_t *sock)
-{
- struct st_h2o_evloop_poll_t *loop = (struct st_h2o_evloop_poll_t *)sock->loop;
-
- if (sock->fd != -1)
- loop->socks.entries[sock->fd] = NULL;
-}
-
-static void evloop_do_on_socket_export(struct st_h2o_evloop_socket_t *sock)
-{
- struct st_h2o_evloop_poll_t *loop = (struct st_h2o_evloop_poll_t *)sock->loop;
- evloop_do_on_socket_close(sock);
- loop->socks.entries[sock->fd] = NULL;
-}
-
-h2o_evloop_t *h2o_evloop_create(void)
-{
- struct st_h2o_evloop_poll_t *loop = (struct st_h2o_evloop_poll_t *)create_evloop(sizeof(*loop));
- return &loop->super;
-}
diff --git a/web/server/h2o/libh2o/lib/common/socket/uv-binding.c.h b/web/server/h2o/libh2o/lib/common/socket/uv-binding.c.h
deleted file mode 100644
index 44c71c166..000000000
--- a/web/server/h2o/libh2o/lib/common/socket/uv-binding.c.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Fastly, Inc.
- *
- * 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.
- */
-
-struct st_h2o_uv_socket_t {
- h2o_socket_t super;
- struct {
- uv_stream_t *stream;
- uv_close_cb close_cb;
- } uv;
- union {
- uv_connect_t _creq;
- uv_write_t _wreq;
- };
-};
-
-static void schedule_timer(h2o_timeout_t *timeout);
-
-static void alloc_inbuf_tcp(uv_handle_t *handle, size_t suggested_size, uv_buf_t *_buf)
-{
- struct st_h2o_uv_socket_t *sock = handle->data;
-
- h2o_iovec_t buf = h2o_buffer_reserve(&sock->super.input, 4096);
- memcpy(_buf, &buf, sizeof(buf));
-}
-
-static void alloc_inbuf_ssl(uv_handle_t *handle, size_t suggested_size, uv_buf_t *_buf)
-{
- struct st_h2o_uv_socket_t *sock = handle->data;
-
- h2o_iovec_t buf = h2o_buffer_reserve(&sock->super.ssl->input.encrypted, 4096);
- memcpy(_buf, &buf, sizeof(buf));
-}
-
-static void on_read_tcp(uv_stream_t *stream, ssize_t nread, const uv_buf_t *_unused)
-{
- struct st_h2o_uv_socket_t *sock = stream->data;
-
- if (nread < 0) {
- sock->super.bytes_read = 0;
- sock->super._cb.read(&sock->super, h2o_socket_error_closed);
- return;
- }
-
- sock->super.input->size += nread;
- sock->super.bytes_read = nread;
- sock->super._cb.read(&sock->super, NULL);
-}
-
-static void on_read_ssl(uv_stream_t *stream, ssize_t nread, const uv_buf_t *_unused)
-{
- struct st_h2o_uv_socket_t *sock = stream->data;
- size_t prev_bytes_read = sock->super.input->size;
- const char *err = h2o_socket_error_io;
-
- if (nread > 0) {
- sock->super.ssl->input.encrypted->size += nread;
- if (sock->super.ssl->handshake.cb == NULL)
- err = decode_ssl_input(&sock->super);
- else
- err = NULL;
- }
- sock->super.bytes_read = sock->super.input->size - prev_bytes_read;
- sock->super._cb.read(&sock->super, err);
-}
-
-static void on_do_write_complete(uv_write_t *wreq, int status)
-{
- struct st_h2o_uv_socket_t *sock = H2O_STRUCT_FROM_MEMBER(struct st_h2o_uv_socket_t, _wreq, wreq);
- if (sock->super._cb.write != NULL)
- on_write_complete(&sock->super, status == 0 ? NULL : h2o_socket_error_io);
-}
-
-static void free_sock(uv_handle_t *handle)
-{
- struct st_h2o_uv_socket_t *sock = handle->data;
- uv_close_cb cb = sock->uv.close_cb;
- free(sock);
- cb(handle);
-}
-
-void do_dispose_socket(h2o_socket_t *_sock)
-{
- struct st_h2o_uv_socket_t *sock = (struct st_h2o_uv_socket_t *)_sock;
- sock->super._cb.write = NULL; /* avoid the write callback getting called when closing the socket (#1249) */
- uv_close((uv_handle_t *)sock->uv.stream, free_sock);
-}
-
-int h2o_socket_get_fd(h2o_socket_t *_sock)
-{
- int fd, ret;
- struct st_h2o_uv_socket_t *sock = (struct st_h2o_uv_socket_t *)_sock;
-
- ret = uv_fileno((uv_handle_t *)sock->uv.stream, (uv_os_fd_t *)&fd);
- if (ret)
- return -1;
-
- return fd;
-}
-
-void do_read_start(h2o_socket_t *_sock)
-{
- struct st_h2o_uv_socket_t *sock = (struct st_h2o_uv_socket_t *)_sock;
-
- if (sock->super.ssl == NULL)
- uv_read_start(sock->uv.stream, alloc_inbuf_tcp, on_read_tcp);
- else
- uv_read_start(sock->uv.stream, alloc_inbuf_ssl, on_read_ssl);
-}
-
-void do_read_stop(h2o_socket_t *_sock)
-{
- struct st_h2o_uv_socket_t *sock = (struct st_h2o_uv_socket_t *)_sock;
- uv_read_stop(sock->uv.stream);
-}
-
-void do_write(h2o_socket_t *_sock, h2o_iovec_t *bufs, size_t bufcnt, h2o_socket_cb cb)
-{
- struct st_h2o_uv_socket_t *sock = (struct st_h2o_uv_socket_t *)_sock;
-
- assert(sock->super._cb.write == NULL);
- sock->super._cb.write = cb;
-
- uv_write(&sock->_wreq, sock->uv.stream, (uv_buf_t *)bufs, (int)bufcnt, on_do_write_complete);
-}
-
-static struct st_h2o_uv_socket_t *create_socket(h2o_loop_t *loop)
-{
- uv_tcp_t *tcp = h2o_mem_alloc(sizeof(*tcp));
-
- if (uv_tcp_init(loop, tcp) != 0) {
- free(tcp);
- return NULL;
- }
- return (void *)h2o_uv_socket_create((void *)tcp, (uv_close_cb)free);
-}
-
-int do_export(h2o_socket_t *_sock, h2o_socket_export_t *info)
-{
- struct st_h2o_uv_socket_t *sock = (void *)_sock;
- uv_os_fd_t fd;
-
- if (uv_fileno((uv_handle_t *)sock->uv.stream, &fd) != 0)
- return -1;
- /* FIXME: consider how to overcome the epoll(2) problem; man says,
- * "even after a file descriptor that is part of an epoll set has been closed,
- * events may be reported for that file descriptor if other file descriptors
- * referring to the same underlying file description remain open"
- */
- if ((info->fd = dup(fd)) == -1)
- return -1;
- return 0;
-}
-
-h2o_socket_t *do_import(h2o_loop_t *loop, h2o_socket_export_t *info)
-{
- struct st_h2o_uv_socket_t *sock = create_socket(loop);
-
- if (sock == NULL)
- return NULL;
- if (uv_tcp_open((uv_tcp_t *)sock->uv.stream, info->fd) != 0) {
- h2o_socket_close(&sock->super);
- return NULL;
- }
-
- return &sock->super;
-}
-
-h2o_socket_t *h2o_uv_socket_create(uv_stream_t *stream, uv_close_cb close_cb)
-{
- struct st_h2o_uv_socket_t *sock = h2o_mem_alloc(sizeof(*sock));
-
- memset(sock, 0, sizeof(*sock));
- h2o_buffer_init(&sock->super.input, &h2o_socket_buffer_prototype);
- sock->uv.stream = stream;
- sock->uv.close_cb = close_cb;
- stream->data = sock;
- return &sock->super;
-}
-
-static void on_connect(uv_connect_t *conn, int status)
-{
- if (status == UV_ECANCELED)
- return;
- struct st_h2o_uv_socket_t *sock = H2O_STRUCT_FROM_MEMBER(struct st_h2o_uv_socket_t, _creq, conn);
- h2o_socket_cb cb = sock->super._cb.write;
- sock->super._cb.write = NULL;
- cb(&sock->super, status == 0 ? NULL : h2o_socket_error_conn_fail);
-}
-
-h2o_loop_t *h2o_socket_get_loop(h2o_socket_t *_sock)
-{
- struct st_h2o_uv_socket_t *sock = (void *)_sock;
- return sock->uv.stream->loop;
-}
-
-h2o_socket_t *h2o_socket_connect(h2o_loop_t *loop, struct sockaddr *addr, socklen_t addrlen, h2o_socket_cb cb)
-{
- struct st_h2o_uv_socket_t *sock = create_socket(loop);
-
- if (sock == NULL)
- return NULL;
- if (uv_tcp_connect(&sock->_creq, (void *)sock->uv.stream, addr, on_connect) != 0) {
- h2o_socket_close(&sock->super);
- return NULL;
- }
- sock->super._cb.write = cb;
- return &sock->super;
-}
-
-socklen_t h2o_socket_getsockname(h2o_socket_t *_sock, struct sockaddr *sa)
-{
- struct st_h2o_uv_socket_t *sock = (void *)_sock;
- int len = sizeof(struct sockaddr_storage);
- if (uv_tcp_getsockname((void *)sock->uv.stream, sa, &len) != 0)
- return 0;
- return (socklen_t)len;
-}
-
-socklen_t get_peername_uncached(h2o_socket_t *_sock, struct sockaddr *sa)
-{
- struct st_h2o_uv_socket_t *sock = (void *)_sock;
- int len = sizeof(struct sockaddr_storage);
- if (uv_tcp_getpeername((void *)sock->uv.stream, sa, &len) != 0)
- return 0;
- return (socklen_t)len;
-}
-
-static void on_timeout(uv_timer_t *timer)
-{
- h2o_timeout_t *timeout = H2O_STRUCT_FROM_MEMBER(h2o_timeout_t, _backend.timer, timer);
-
- h2o_timeout_run(timer->loop, timeout, h2o_now(timer->loop));
- if (!h2o_linklist_is_empty(&timeout->_entries))
- schedule_timer(timeout);
-}
-
-void schedule_timer(h2o_timeout_t *timeout)
-{
- h2o_timeout_entry_t *entry = H2O_STRUCT_FROM_MEMBER(h2o_timeout_entry_t, _link, timeout->_entries.next);
- uv_timer_start(&timeout->_backend.timer, on_timeout,
- entry->registered_at + timeout->timeout - h2o_now(timeout->_backend.timer.loop), 0);
-}
-
-void h2o_timeout__do_init(h2o_loop_t *loop, h2o_timeout_t *timeout)
-{
- uv_timer_init(loop, &timeout->_backend.timer);
-}
-
-void h2o_timeout__do_dispose(h2o_loop_t *loop, h2o_timeout_t *timeout)
-{
- uv_close((uv_handle_t *)&timeout->_backend.timer, NULL);
-}
-
-void h2o_timeout__do_link(h2o_loop_t *loop, h2o_timeout_t *timeout, h2o_timeout_entry_t *entry)
-{
- /* register the timer if the entry just being added is the only entry */
- if (timeout->_entries.next == &entry->_link)
- schedule_timer(timeout);
-}
-
-void h2o_timeout__do_post_callback(h2o_loop_t *loop)
-{
- /* nothing to do */
-}
diff --git a/web/server/h2o/libh2o/lib/common/socketpool.c b/web/server/h2o/libh2o/lib/common/socketpool.c
deleted file mode 100644
index da69933f7..000000000
--- a/web/server/h2o/libh2o/lib/common/socketpool.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <assert.h>
-#include <errno.h>
-#include <netdb.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include "h2o/hostinfo.h"
-#include "h2o/linklist.h"
-#include "h2o/socketpool.h"
-#include "h2o/string_.h"
-#include "h2o/timeout.h"
-
-struct pool_entry_t {
- h2o_socket_export_t sockinfo;
- h2o_linklist_t link;
- uint64_t added_at;
-};
-
-struct st_h2o_socketpool_connect_request_t {
- void *data;
- h2o_socketpool_connect_cb cb;
- h2o_socketpool_t *pool;
- h2o_loop_t *loop;
- h2o_hostinfo_getaddr_req_t *getaddr_req;
- h2o_socket_t *sock;
-};
-
-static void destroy_detached(struct pool_entry_t *entry)
-{
- h2o_socket_dispose_export(&entry->sockinfo);
- free(entry);
-}
-
-static void destroy_attached(struct pool_entry_t *entry)
-{
- h2o_linklist_unlink(&entry->link);
- destroy_detached(entry);
-}
-
-static void destroy_expired(h2o_socketpool_t *pool)
-{
- /* caller should lock the mutex */
- uint64_t expire_before = h2o_now(pool->_interval_cb.loop) - pool->timeout;
- while (!h2o_linklist_is_empty(&pool->_shared.sockets)) {
- struct pool_entry_t *entry = H2O_STRUCT_FROM_MEMBER(struct pool_entry_t, link, pool->_shared.sockets.next);
- if (entry->added_at > expire_before)
- break;
- destroy_attached(entry);
- __sync_sub_and_fetch(&pool->_shared.count, 1);
- }
-}
-
-static void on_timeout(h2o_timeout_entry_t *timeout_entry)
-{
- /* FIXME decrease the frequency of this function being called; the expiration
- * check can be (should be) performed in the `connect` fuction as well
- */
- h2o_socketpool_t *pool = H2O_STRUCT_FROM_MEMBER(h2o_socketpool_t, _interval_cb.entry, timeout_entry);
-
- if (pthread_mutex_trylock(&pool->_shared.mutex) == 0) {
- destroy_expired(pool);
- pthread_mutex_unlock(&pool->_shared.mutex);
- }
-
- h2o_timeout_link(pool->_interval_cb.loop, &pool->_interval_cb.timeout, &pool->_interval_cb.entry);
-}
-
-static void common_init(h2o_socketpool_t *pool, h2o_socketpool_type_t type, h2o_iovec_t host, int is_ssl, size_t capacity)
-{
- memset(pool, 0, sizeof(*pool));
-
- pool->type = type;
- pool->peer.host = h2o_strdup(NULL, host.base, host.len);
- pool->is_ssl = is_ssl;
- pool->capacity = capacity;
- pool->timeout = UINT64_MAX;
-
- pthread_mutex_init(&pool->_shared.mutex, NULL);
- h2o_linklist_init_anchor(&pool->_shared.sockets);
-}
-
-void h2o_socketpool_init_by_address(h2o_socketpool_t *pool, struct sockaddr *sa, socklen_t salen, int is_ssl, size_t capacity)
-{
- char host[NI_MAXHOST];
- size_t host_len;
-
- assert(salen <= sizeof(pool->peer.sockaddr.bytes));
-
- if ((host_len = h2o_socket_getnumerichost(sa, salen, host)) == SIZE_MAX) {
- if (sa->sa_family != AF_UNIX)
- h2o_fatal("failed to convert a non-unix socket address to a numerical representation");
- /* use the sockaddr_un::sun_path as the SNI indicator (is that the right thing to do?) */
- strcpy(host, ((struct sockaddr_un *)sa)->sun_path);
- host_len = strlen(host);
- }
-
- common_init(pool, H2O_SOCKETPOOL_TYPE_SOCKADDR, h2o_iovec_init(host, host_len), is_ssl, capacity);
- memcpy(&pool->peer.sockaddr.bytes, sa, salen);
- pool->peer.sockaddr.len = salen;
-}
-
-void h2o_socketpool_init_by_hostport(h2o_socketpool_t *pool, h2o_iovec_t host, uint16_t port, int is_ssl, size_t capacity)
-{
- struct sockaddr_in sin;
- memset(&sin, 0, sizeof(sin));
-
- if (h2o_hostinfo_aton(host, &sin.sin_addr) == 0) {
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- h2o_socketpool_init_by_address(pool, (void *)&sin, sizeof(sin), is_ssl, capacity);
- return;
- }
-
- common_init(pool, H2O_SOCKETPOOL_TYPE_NAMED, host, is_ssl, capacity);
- pool->peer.named_serv.base = h2o_mem_alloc(sizeof(H2O_UINT16_LONGEST_STR));
- pool->peer.named_serv.len = sprintf(pool->peer.named_serv.base, "%u", (unsigned)port);
-}
-
-void h2o_socketpool_dispose(h2o_socketpool_t *pool)
-{
- pthread_mutex_lock(&pool->_shared.mutex);
- while (!h2o_linklist_is_empty(&pool->_shared.sockets)) {
- struct pool_entry_t *entry = H2O_STRUCT_FROM_MEMBER(struct pool_entry_t, link, pool->_shared.sockets.next);
- destroy_attached(entry);
- __sync_sub_and_fetch(&pool->_shared.count, 1);
- }
- pthread_mutex_unlock(&pool->_shared.mutex);
- pthread_mutex_destroy(&pool->_shared.mutex);
-
- if (pool->_interval_cb.loop != NULL) {
- h2o_timeout_unlink(&pool->_interval_cb.entry);
- h2o_timeout_dispose(pool->_interval_cb.loop, &pool->_interval_cb.timeout);
- }
- free(pool->peer.host.base);
- switch (pool->type) {
- case H2O_SOCKETPOOL_TYPE_NAMED:
- free(pool->peer.named_serv.base);
- break;
- case H2O_SOCKETPOOL_TYPE_SOCKADDR:
- break;
- }
-}
-
-void h2o_socketpool_set_timeout(h2o_socketpool_t *pool, h2o_loop_t *loop, uint64_t msec)
-{
- pool->timeout = msec;
-
- pool->_interval_cb.loop = loop;
- h2o_timeout_init(loop, &pool->_interval_cb.timeout, 1000);
- pool->_interval_cb.entry.cb = on_timeout;
-
- h2o_timeout_link(loop, &pool->_interval_cb.timeout, &pool->_interval_cb.entry);
-}
-
-static void call_connect_cb(h2o_socketpool_connect_request_t *req, const char *errstr)
-{
- h2o_socketpool_connect_cb cb = req->cb;
- h2o_socket_t *sock = req->sock;
- void *data = req->data;
-
- free(req);
- cb(sock, errstr, data);
-}
-
-static void on_connect(h2o_socket_t *sock, const char *err)
-{
- h2o_socketpool_connect_request_t *req = sock->data;
- const char *errstr = NULL;
-
- assert(req->sock == sock);
-
- if (err != NULL) {
- h2o_socket_close(sock);
- req->sock = NULL;
- errstr = "connection failed";
- }
- call_connect_cb(req, errstr);
-}
-
-static void on_close(void *data)
-{
- h2o_socketpool_t *pool = data;
- __sync_sub_and_fetch(&pool->_shared.count, 1);
-}
-
-static void start_connect(h2o_socketpool_connect_request_t *req, struct sockaddr *addr, socklen_t addrlen)
-{
- req->sock = h2o_socket_connect(req->loop, addr, addrlen, on_connect);
- if (req->sock == NULL) {
- __sync_sub_and_fetch(&req->pool->_shared.count, 1);
- call_connect_cb(req, "failed to connect to host");
- return;
- }
- req->sock->data = req;
- req->sock->on_close.cb = on_close;
- req->sock->on_close.data = req->pool;
-}
-
-static void on_getaddr(h2o_hostinfo_getaddr_req_t *getaddr_req, const char *errstr, struct addrinfo *res, void *_req)
-{
- h2o_socketpool_connect_request_t *req = _req;
-
- assert(getaddr_req == req->getaddr_req);
- req->getaddr_req = NULL;
-
- if (errstr != NULL) {
- __sync_sub_and_fetch(&req->pool->_shared.count, 1);
- call_connect_cb(req, errstr);
- return;
- }
-
- struct addrinfo *selected = h2o_hostinfo_select_one(res);
- start_connect(req, selected->ai_addr, selected->ai_addrlen);
-}
-
-void h2o_socketpool_connect(h2o_socketpool_connect_request_t **_req, h2o_socketpool_t *pool, h2o_loop_t *loop,
- h2o_multithread_receiver_t *getaddr_receiver, h2o_socketpool_connect_cb cb, void *data)
-{
- struct pool_entry_t *entry = NULL;
-
- if (_req != NULL)
- *_req = NULL;
-
- /* fetch an entry and return it */
- pthread_mutex_lock(&pool->_shared.mutex);
- destroy_expired(pool);
- while (1) {
- if (h2o_linklist_is_empty(&pool->_shared.sockets))
- break;
- entry = H2O_STRUCT_FROM_MEMBER(struct pool_entry_t, link, pool->_shared.sockets.next);
- h2o_linklist_unlink(&entry->link);
- pthread_mutex_unlock(&pool->_shared.mutex);
-
- /* test if the connection is still alive */
- char buf[1];
- ssize_t rret = recv(entry->sockinfo.fd, buf, 1, MSG_PEEK);
- if (rret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
- /* yes! return it */
- h2o_socket_t *sock = h2o_socket_import(loop, &entry->sockinfo);
- free(entry);
- sock->on_close.cb = on_close;
- sock->on_close.data = pool;
- cb(sock, NULL, data);
- return;
- }
-
- /* connection is dead, report, close, and retry */
- if (rret <= 0) {
- static long counter = 0;
- if (__sync_fetch_and_add(&counter, 1) == 0)
- fprintf(stderr, "[WARN] detected close by upstream before the expected timeout (see issue #679)\n");
- } else {
- static long counter = 0;
- if (__sync_fetch_and_add(&counter, 1) == 0)
- fprintf(stderr, "[WARN] unexpectedly received data to a pooled socket (see issue #679)\n");
- }
- destroy_detached(entry);
- pthread_mutex_lock(&pool->_shared.mutex);
- }
- pthread_mutex_unlock(&pool->_shared.mutex);
-
- /* FIXME repsect `capacity` */
- __sync_add_and_fetch(&pool->_shared.count, 1);
-
- /* prepare request object */
- h2o_socketpool_connect_request_t *req = h2o_mem_alloc(sizeof(*req));
- *req = (h2o_socketpool_connect_request_t){data, cb, pool, loop};
- if (_req != NULL)
- *_req = req;
-
- switch (pool->type) {
- case H2O_SOCKETPOOL_TYPE_NAMED:
- /* resolve the name, and connect */
- req->getaddr_req = h2o_hostinfo_getaddr(getaddr_receiver, pool->peer.host, pool->peer.named_serv, AF_UNSPEC, SOCK_STREAM,
- IPPROTO_TCP, AI_ADDRCONFIG | AI_NUMERICSERV, on_getaddr, req);
- break;
- case H2O_SOCKETPOOL_TYPE_SOCKADDR:
- /* connect (using sockaddr_in) */
- start_connect(req, (void *)&pool->peer.sockaddr.bytes, pool->peer.sockaddr.len);
- break;
- }
-}
-
-void h2o_socketpool_cancel_connect(h2o_socketpool_connect_request_t *req)
-{
- if (req->getaddr_req != NULL) {
- h2o_hostinfo_getaddr_cancel(req->getaddr_req);
- req->getaddr_req = NULL;
- }
- if (req->sock != NULL)
- h2o_socket_close(req->sock);
- free(req);
-}
-
-int h2o_socketpool_return(h2o_socketpool_t *pool, h2o_socket_t *sock)
-{
- struct pool_entry_t *entry;
-
- /* reset the on_close callback */
- assert(sock->on_close.data == pool);
- sock->on_close.cb = NULL;
- sock->on_close.data = NULL;
-
- entry = h2o_mem_alloc(sizeof(*entry));
- if (h2o_socket_export(sock, &entry->sockinfo) != 0) {
- free(entry);
- __sync_sub_and_fetch(&pool->_shared.count, 1);
- return -1;
- }
- memset(&entry->link, 0, sizeof(entry->link));
- entry->added_at = h2o_now(h2o_socket_get_loop(sock));
-
- pthread_mutex_lock(&pool->_shared.mutex);
- destroy_expired(pool);
- h2o_linklist_insert(&pool->_shared.sockets, &entry->link);
- pthread_mutex_unlock(&pool->_shared.mutex);
-
- return 0;
-}
diff --git a/web/server/h2o/libh2o/lib/common/string.c b/web/server/h2o/libh2o/lib/common/string.c
deleted file mode 100644
index 3c068f3ad..000000000
--- a/web/server/h2o/libh2o/lib/common/string.c
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Justin Zhu, Fastly, Inc.
- *
- * 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 <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "h2o/string_.h"
-
-h2o_iovec_t h2o_strdup(h2o_mem_pool_t *pool, const char *s, size_t slen)
-{
- h2o_iovec_t ret;
-
- if (slen == SIZE_MAX)
- slen = strlen(s);
-
- if (pool != NULL) {
- ret.base = h2o_mem_alloc_pool(pool, slen + 1);
- } else {
- ret.base = h2o_mem_alloc(slen + 1);
- }
- h2o_memcpy(ret.base, s, slen);
- ret.base[slen] = '\0';
- ret.len = slen;
- return ret;
-}
-
-h2o_iovec_t h2o_strdup_shared(h2o_mem_pool_t *pool, const char *s, size_t slen)
-{
- h2o_iovec_t ret;
-
- if (slen == SIZE_MAX)
- slen = strlen(s);
-
- ret.base = h2o_mem_alloc_shared(pool, slen + 1, NULL);
- memcpy(ret.base, s, slen);
- ret.base[slen] = '\0';
- ret.len = slen;
- return ret;
-}
-
-h2o_iovec_t h2o_strdup_slashed(h2o_mem_pool_t *pool, const char *src, size_t len)
-{
- h2o_iovec_t ret;
-
- ret.len = len != SIZE_MAX ? len : strlen(src);
- ret.base = pool != NULL ? h2o_mem_alloc_pool(pool, ret.len + 2) : h2o_mem_alloc(ret.len + 2);
- memcpy(ret.base, src, ret.len);
- if (ret.len != 0 && ret.base[ret.len - 1] != '/')
- ret.base[ret.len++] = '/';
- ret.base[ret.len] = '\0';
-
- return ret;
-}
-
-int h2o__lcstris_core(const char *target, const char *test, size_t test_len)
-{
- for (; test_len != 0; --test_len)
- if (h2o_tolower(*target++) != *test++)
- return 0;
- return 1;
-}
-
-size_t h2o_strtosize(const char *s, size_t len)
-{
- uint64_t v = 0, m = 1;
- const char *p = s + len;
-
- if (len == 0)
- goto Error;
-
- while (1) {
- int ch = *--p;
- if (!('0' <= ch && ch <= '9'))
- goto Error;
- v += (ch - '0') * m;
- if (p == s)
- break;
- m *= 10;
- /* do not even try to overflow */
- if (m == 10000000000000000000ULL)
- goto Error;
- }
-
- if (v >= SIZE_MAX)
- goto Error;
- return v;
-
-Error:
- return SIZE_MAX;
-}
-
-size_t h2o_strtosizefwd(char **s, size_t len)
-{
- uint64_t v, c;
- char *p = *s, *p_end = *s + len;
-
- if (len == 0)
- goto Error;
-
- int ch = *p++;
- if (!('0' <= ch && ch <= '9'))
- goto Error;
- v = ch - '0';
- c = 1;
-
- while (1) {
- ch = *p;
- if (!('0' <= ch && ch <= '9'))
- break;
- v *= 10;
- v += ch - '0';
- p++;
- c++;
- if (p == p_end)
- break;
- /* similar as above, do not even try to overflow */
- if (c == 20)
- goto Error;
- }
-
- if (v >= SIZE_MAX)
- goto Error;
- *s = p;
- return v;
-
-Error:
- return SIZE_MAX;
-}
-
-static uint32_t decode_base64url_quad(const char *src)
-{
- const char *src_end = src + 4;
- uint32_t decoded = 0;
-
- while (1) {
- if ('A' <= *src && *src <= 'Z') {
- decoded |= *src - 'A';
- } else if ('a' <= *src && *src <= 'z') {
- decoded |= *src - 'a' + 26;
- } else if ('0' <= *src && *src <= '9') {
- decoded |= *src - '0' + 52;
- } else if (*src == '-') {
- decoded |= 62;
- } else if (*src == '_') {
- decoded |= 63;
-#if 1 /* curl uses normal base64 */
- } else if (*src == '+') {
- decoded |= 62;
- } else if (*src == '/') {
- decoded |= 63;
-#endif
- } else {
- return UINT32_MAX;
- }
- if (++src == src_end)
- break;
- decoded <<= 6;
- }
-
- return decoded;
-}
-
-h2o_iovec_t h2o_decode_base64url(h2o_mem_pool_t *pool, const char *src, size_t len)
-{
- h2o_iovec_t decoded;
- uint32_t t;
- uint8_t *dst;
- char remaining_input[4];
-
- decoded.len = len * 3 / 4;
- decoded.base = pool != NULL ? h2o_mem_alloc_pool(pool, decoded.len + 1) : h2o_mem_alloc(decoded.len + 1);
- dst = (uint8_t *)decoded.base;
-
- while (len >= 4) {
- if ((t = decode_base64url_quad(src)) == UINT32_MAX)
- goto Error;
- *dst++ = t >> 16;
- *dst++ = t >> 8;
- *dst++ = t;
- src += 4;
- len -= 4;
- }
- switch (len) {
- case 0:
- break;
- case 1:
- goto Error;
- case 2:
- remaining_input[0] = *src++;
- remaining_input[1] = *src++;
- remaining_input[2] = 'A';
- remaining_input[3] = 'A';
- if ((t = decode_base64url_quad(remaining_input)) == UINT32_MAX)
- goto Error;
- *dst++ = t >> 16;
- break;
- case 3:
- remaining_input[0] = *src++;
- remaining_input[1] = *src++;
- remaining_input[2] = *src++;
- remaining_input[3] = 'A';
- if ((t = decode_base64url_quad(remaining_input)) == UINT32_MAX)
- goto Error;
- *dst++ = t >> 16;
- *dst++ = t >> 8;
- break;
- }
-
- assert((char *)dst - decoded.base == decoded.len);
- decoded.base[decoded.len] = '\0';
-
- return decoded;
-
-Error:
- if (pool == NULL)
- free(decoded.base);
- return h2o_iovec_init(NULL, 0);
-}
-
-size_t h2o_base64_encode(char *_dst, const void *_src, size_t len, int url_encoded)
-{
- static const char *MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
- static const char *MAP_URL_ENCODED = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789-_";
-
- char *dst = _dst;
- const uint8_t *src = _src;
- const char *map = url_encoded ? MAP_URL_ENCODED : MAP;
- uint32_t quad;
-
- for (; len >= 3; src += 3, len -= 3) {
- quad = ((uint32_t)src[0] << 16) | ((uint32_t)src[1] << 8) | src[2];
- *dst++ = map[quad >> 18];
- *dst++ = map[(quad >> 12) & 63];
- *dst++ = map[(quad >> 6) & 63];
- *dst++ = map[quad & 63];
- }
- if (len != 0) {
- quad = (uint32_t)src[0] << 16;
- *dst++ = map[quad >> 18];
- if (len == 2) {
- quad |= (uint32_t)src[1] << 8;
- *dst++ = map[(quad >> 12) & 63];
- *dst++ = map[(quad >> 6) & 63];
- if (!url_encoded)
- *dst++ = '=';
- } else {
- *dst++ = map[(quad >> 12) & 63];
- if (!url_encoded) {
- *dst++ = '=';
- *dst++ = '=';
- }
- }
- }
-
- *dst = '\0';
- return dst - _dst;
-}
-
-static int decode_hex(int ch)
-{
- if ('0' <= ch && ch <= '9')
- return ch - '0';
- if ('A' <= ch && ch <= 'F')
- return ch - 'A' + 0xa;
- if ('a' <= ch && ch <= 'f')
- return ch - 'a' + 0xa;
- return -1;
-}
-
-int h2o_hex_decode(void *_dst, const char *src, size_t src_len)
-{
- unsigned char *dst = _dst;
-
- if (src_len % 2 != 0)
- return -1;
- for (; src_len != 0; src_len -= 2) {
- int hi, lo;
- if ((hi = decode_hex(*src++)) == -1 || (lo = decode_hex(*src++)) == -1)
- return -1;
- *dst++ = (hi << 4) | lo;
- }
- return 0;
-}
-
-void h2o_hex_encode(char *dst, const void *_src, size_t src_len)
-{
- const unsigned char *src = _src, *src_end = src + src_len;
- for (; src != src_end; ++src) {
- *dst++ = "0123456789abcdef"[*src >> 4];
- *dst++ = "0123456789abcdef"[*src & 0xf];
- }
- *dst = '\0';
-}
-
-h2o_iovec_t h2o_uri_escape(h2o_mem_pool_t *pool, const char *s, size_t l, const char *preserve_chars)
-{
- h2o_iovec_t encoded;
- size_t i, capacity = l * 3 + 1;
-
- encoded.base = pool != NULL ? h2o_mem_alloc_pool(pool, capacity) : h2o_mem_alloc(capacity);
- encoded.len = 0;
-
- /* RFC 3986:
- path-noscheme = segment-nz-nc *( "/" segment )
- segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
- unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
- sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
- / "*" / "+" / "," / ";" / "="
- */
- for (i = 0; i != l; ++i) {
- int ch = s[i];
- if (('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z') || ('0' <= ch && ch <= '9') || ch == '-' || ch == '.' ||
- ch == '_' || ch == '~' || ch == '!' || ch == '$' || ch == '&' || ch == '\'' || ch == '(' || ch == ')' || ch == '*' ||
- ch == '+' || ch == ',' || ch == ';' || ch == '=' ||
- (ch != '\0' && preserve_chars != NULL && strchr(preserve_chars, ch) != NULL)) {
- encoded.base[encoded.len++] = ch;
- } else {
- encoded.base[encoded.len++] = '%';
- encoded.base[encoded.len++] = "0123456789ABCDEF"[(ch >> 4) & 0xf];
- encoded.base[encoded.len++] = "0123456789ABCDEF"[ch & 0xf];
- }
- }
- encoded.base[encoded.len] = '\0';
-
- return encoded;
-}
-
-h2o_iovec_t h2o_get_filext(const char *path, size_t len)
-{
- const char *end = path + len, *p = end;
-
- while (--p != path) {
- if (*p == '.') {
- return h2o_iovec_init(p + 1, end - (p + 1));
- } else if (*p == '/') {
- break;
- }
- }
- return h2o_iovec_init(NULL, 0);
-}
-
-static int is_ws(int ch)
-{
- return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
-}
-
-h2o_iovec_t h2o_str_stripws(const char *s, size_t len)
-{
- const char *end = s + len;
-
- while (s != end) {
- if (!is_ws(*s))
- break;
- ++s;
- }
- while (s != end) {
- if (!is_ws(end[-1]))
- break;
- --end;
- }
- return h2o_iovec_init(s, end - s);
-}
-
-size_t h2o_strstr(const char *haysack, size_t haysack_len, const char *needle, size_t needle_len)
-{
- /* TODO optimize */
- if (haysack_len >= needle_len) {
- size_t off, max = haysack_len - needle_len + 1;
- if (needle_len == 0)
- return 0;
- for (off = 0; off != max; ++off)
- if (haysack[off] == needle[0] && memcmp(haysack + off + 1, needle + 1, needle_len - 1) == 0)
- return off;
- }
- return SIZE_MAX;
-}
-
-/* note: returns a zero-width match as well */
-const char *h2o_next_token(h2o_iovec_t *iter, int separator, size_t *element_len, h2o_iovec_t *value)
-{
- const char *cur = iter->base, *end = iter->base + iter->len, *token_start, *token_end;
-
- /* find start */
- for (;; ++cur) {
- if (cur == end)
- return NULL;
- if (!(*cur == ' ' || *cur == '\t'))
- break;
- }
- token_start = cur;
- token_end = cur;
-
- /* find last */
- for (;; ++cur) {
- if (cur == end)
- break;
- if (*cur == separator) {
- ++cur;
- break;
- }
- if (*cur == ',') {
- if (token_start == cur) {
- ++cur;
- token_end = cur;
- }
- break;
- }
- if (value != NULL && *cur == '=') {
- ++cur;
- goto FindValue;
- }
- if (!(*cur == ' ' || *cur == '\t'))
- token_end = cur + 1;
- }
-
- /* found */
- *iter = h2o_iovec_init(cur, end - cur);
- *element_len = token_end - token_start;
- if (value != NULL)
- *value = (h2o_iovec_t){NULL};
- return token_start;
-
-FindValue:
- *iter = h2o_iovec_init(cur, end - cur);
- *element_len = token_end - token_start;
- if ((value->base = (char *)h2o_next_token(iter, separator, &value->len, NULL)) == NULL) {
- *value = (h2o_iovec_t){"", 0};
- } else if (h2o_memis(value->base, value->len, H2O_STRLIT(","))) {
- *value = (h2o_iovec_t){"", 0};
- iter->base -= 1;
- iter->len += 1;
- }
- return token_start;
-}
-
-int h2o_contains_token(const char *haysack, size_t haysack_len, const char *needle, size_t needle_len, int separator)
-{
- h2o_iovec_t iter = h2o_iovec_init(haysack, haysack_len);
- const char *token = NULL;
- size_t token_len = 0;
-
- while ((token = h2o_next_token(&iter, separator, &token_len, NULL)) != NULL) {
- if (h2o_lcstris(token, token_len, needle, needle_len)) {
- return 1;
- }
- }
- return 0;
-}
-
-h2o_iovec_t h2o_htmlescape(h2o_mem_pool_t *pool, const char *src, size_t len)
-{
- const char *s, *end = src + len;
- size_t add_size = 0;
-
-#define ENTITY_MAP() \
- ENTITY('"', "&quot;"); \
- ENTITY('&', "&amp;"); \
- ENTITY('\'', "&#39;"); \
- ENTITY('<', "&lt;"); \
- ENTITY('>', "&gt;");
-
- for (s = src; s != end; ++s) {
- if ((unsigned)(unsigned char)*s - '"' <= '>' - '"') {
- switch (*s) {
-#define ENTITY(code, quoted) \
- case code: \
- add_size += sizeof(quoted) - 2; \
- break
- ENTITY_MAP()
-#undef ENTITY
- }
- }
- }
-
- /* escape and return the result if necessary */
- if (add_size != 0) {
- /* allocate buffer and fill in the chars that are known not to require escaping */
- h2o_iovec_t escaped = {h2o_mem_alloc_pool(pool, len + add_size + 1), 0};
- /* fill-in the rest */
- for (s = src; s != end; ++s) {
- switch (*s) {
-#define ENTITY(code, quoted) \
- case code: \
- memcpy(escaped.base + escaped.len, quoted, sizeof(quoted) - 1); \
- escaped.len += sizeof(quoted) - 1; \
- break
- ENTITY_MAP()
-#undef ENTITY
- default:
- escaped.base[escaped.len++] = *s;
- break;
- }
- }
- assert(escaped.len == len + add_size);
- escaped.base[escaped.len] = '\0';
-
- return escaped;
- }
-
-#undef ENTITY_MAP
-
- /* no need not escape; return the original */
- return h2o_iovec_init(src, len);
-}
-
-h2o_iovec_t h2o_concat_list(h2o_mem_pool_t *pool, h2o_iovec_t *list, size_t count)
-{
- h2o_iovec_t ret = {NULL, 0};
- size_t i;
-
- /* calc the length */
- for (i = 0; i != count; ++i) {
- ret.len += list[i].len;
- }
-
- /* allocate memory */
- if (pool != NULL)
- ret.base = h2o_mem_alloc_pool(pool, ret.len + 1);
- else
- ret.base = h2o_mem_alloc(ret.len + 1);
-
- /* concatenate */
- ret.len = 0;
- for (i = 0; i != count; ++i) {
- h2o_memcpy(ret.base + ret.len, list[i].base, list[i].len);
- ret.len += list[i].len;
- }
- ret.base[ret.len] = '\0';
-
- return ret;
-}
-
-int h2o_str_at_position(char *buf, const char *src, size_t src_len, int lineno, int column)
-{
- const char *src_end = src + src_len;
- int i;
-
- /* find the line */
- if (lineno <= 0 || column <= 0)
- return -1;
- for (--lineno; lineno != 0; --lineno) {
- do {
- if (src == src_end)
- return -1;
- } while (*src++ != '\n');
- }
-
- /* adjust the starting column */
- while (column > 40) {
- if (src != src_end)
- ++src;
- --column;
- }
-
- /* emit */
- for (i = 1; i <= 76; ++i) {
- if (src == src_end || *src == '\n')
- break;
- *buf++ = *src++;
- }
- if (i < column)
- column = i;
- *buf++ = '\n';
- for (i = 1; i < column; ++i)
- *buf++ = ' ';
- *buf++ = '^';
- *buf++ = '\n';
- *buf = '\0';
- return 0;
-}
diff --git a/web/server/h2o/libh2o/lib/common/time.c b/web/server/h2o/libh2o/lib/common/time.c
deleted file mode 100644
index 368143e78..000000000
--- a/web/server/h2o/libh2o/lib/common/time.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2015 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 <assert.h>
-#include <stdio.h>
-#include <string.h>
-#include "h2o/time_.h"
-
-static char *emit_wday(char *dst, int wday)
-{
- memcpy(dst, ("SunMonTueWedThuFriSat") + wday * 3, 3);
- return dst + 3;
-}
-
-static char *emit_mon(char *dst, int mon)
-{
- memcpy(dst, ("JanFebMarAprMayJunJulAugSepOctNovDec") + mon * 3, 3);
- return dst + 3;
-}
-
-static char *emit_digits(char *dst, int n, size_t cnt)
-{
- char *p = dst + cnt;
-
- /* emit digits from back */
- do {
- *--p = '0' + n % 10;
- n /= 10;
- } while (p != dst);
-
- return dst + cnt;
-}
-
-void h2o_time2str_rfc1123(char *buf, struct tm *gmt)
-{
- char *p = buf;
-
- /* format: Fri, 19 Sep 2014 05:24:04 GMT */
- p = emit_wday(p, gmt->tm_wday);
- *p++ = ',';
- *p++ = ' ';
- p = emit_digits(p, gmt->tm_mday, 2);
- *p++ = ' ';
- p = emit_mon(p, gmt->tm_mon);
- *p++ = ' ';
- p = emit_digits(p, gmt->tm_year + 1900, 4);
- *p++ = ' ';
- p = emit_digits(p, gmt->tm_hour, 2);
- *p++ = ':';
- p = emit_digits(p, gmt->tm_min, 2);
- *p++ = ':';
- p = emit_digits(p, gmt->tm_sec, 2);
- memcpy(p, " GMT", 4);
- p += 4;
- *p = '\0';
-
- assert(p - buf == H2O_TIMESTR_RFC1123_LEN);
-}
-
-static int fetch_digits(const char *s, size_t n)
-{
- int value = 0;
- for (; n != 0; ++s, --n) {
- if (!('0' <= *s && *s <= '9'))
- return -1;
- value = value * 10 + *s - '0';
- }
- return value;
-}
-
-int h2o_time_parse_rfc1123(const char *s, size_t len, struct tm *tm)
-{
- if (len != H2O_TIMESTR_RFC1123_LEN)
- return -1;
-
-/* 1 2
- * 01234567890123456789012345678
- * Fri, 19 Sep 2014 05:24:04 GMT
- */
-
-#define FETCH(dst, pos, n) \
- if ((dst = fetch_digits(s + pos, n)) == -1) \
- return -1;
- FETCH(tm->tm_year, 12, 4);
- tm->tm_year -= 1900;
- /* month is parsed afterwards */
- FETCH(tm->tm_mday, 5, 2);
- FETCH(tm->tm_hour, 17, 2);
- FETCH(tm->tm_min, 20, 2);
- FETCH(tm->tm_sec, 23, 2);
-#undef FETCH
-
-#define PACK3(a, b, c) (((a)&0xff) << 16 | ((b)&0xff) << 8 | ((c)&0xff))
-#define MAP(c1, c2, c3, value) \
- case PACK3(c1, c2, c3): \
- tm->tm_mon = value; \
- break
- switch (PACK3(s[8], s[9], s[10])) {
- MAP('J', 'a', 'n', 0);
- MAP('F', 'e', 'b', 1);
- MAP('M', 'a', 'r', 2);
- MAP('A', 'p', 'r', 3);
- MAP('M', 'a', 'y', 4);
- MAP('J', 'u', 'n', 5);
- MAP('J', 'u', 'l', 6);
- MAP('A', 'u', 'g', 7);
- MAP('S', 'e', 'p', 8);
- MAP('O', 'c', 't', 9);
- MAP('N', 'o', 'v', 10);
- MAP('D', 'e', 'c', 11);
- default:
- return -1;
- }
-#undef MAP
-#undef PACK3
-
- return 0;
-}
-
-static int calc_gmt_offset(time_t t, struct tm *local)
-{
- struct tm gmt;
- int delta;
-
- gmtime_r(&t, &gmt);
- delta = (local->tm_hour - gmt.tm_hour) * 60 + (local->tm_min - gmt.tm_min);
-
- if (local->tm_yday != gmt.tm_yday) {
- int day_offset;
- if (local->tm_year == gmt.tm_year)
- day_offset = local->tm_yday - gmt.tm_yday;
- else
- day_offset = local->tm_year - gmt.tm_year;
- delta += day_offset * 24 * 60;
- }
- return delta;
-}
-
-void h2o_time2str_log(char *buf, time_t time)
-{
- struct tm localt;
- localtime_r(&time, &localt);
- int gmt_off = calc_gmt_offset(time, &localt);
- int gmt_sign;
-
- if (gmt_off >= 0) {
- gmt_sign = '+';
- } else {
- gmt_off = -gmt_off;
- gmt_sign = '-';
- }
-
- int len = sprintf(buf, "%02d/%s/%d:%02d:%02d:%02d %c%02d%02d", localt.tm_mday,
- ("Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec\0") + localt.tm_mon * 4, localt.tm_year + 1900,
- localt.tm_hour, localt.tm_min, localt.tm_sec, gmt_sign, gmt_off / 60, gmt_off % 60);
- assert(len == H2O_TIMESTR_LOG_LEN);
-}
diff --git a/web/server/h2o/libh2o/lib/common/timeout.c b/web/server/h2o/libh2o/lib/common/timeout.c
deleted file mode 100644
index c50be0a3f..000000000
--- a/web/server/h2o/libh2o/lib/common/timeout.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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 "h2o/timeout.h"
-
-void h2o_timeout_run(h2o_loop_t *loop, h2o_timeout_t *timeout, uint64_t now)
-{
- uint64_t max_registered_at = now - timeout->timeout;
-
- while (!h2o_linklist_is_empty(&timeout->_entries)) {
- h2o_timeout_entry_t *entry = H2O_STRUCT_FROM_MEMBER(h2o_timeout_entry_t, _link, timeout->_entries.next);
- if (entry->registered_at > max_registered_at) {
- break;
- }
- h2o_linklist_unlink(&entry->_link);
- entry->registered_at = 0;
- entry->cb(entry);
- h2o_timeout__do_post_callback(loop);
- }
-}
-
-uint64_t h2o_timeout_get_wake_at(h2o_linklist_t *timeouts)
-{
- h2o_linklist_t *node;
- uint64_t wake_at = UINT64_MAX;
-
- /* change wake_at to the minimum value of the timeouts */
- for (node = timeouts->next; node != timeouts; node = node->next) {
- h2o_timeout_t *timeout = H2O_STRUCT_FROM_MEMBER(h2o_timeout_t, _link, node);
- if (!h2o_linklist_is_empty(&timeout->_entries)) {
- h2o_timeout_entry_t *entry = H2O_STRUCT_FROM_MEMBER(h2o_timeout_entry_t, _link, timeout->_entries.next);
- uint64_t entry_wake_at = entry->registered_at + timeout->timeout;
- if (entry_wake_at < wake_at)
- wake_at = entry_wake_at;
- }
- }
-
- return wake_at;
-}
-
-void h2o_timeout_init(h2o_loop_t *loop, h2o_timeout_t *timeout, uint64_t millis)
-{
- memset(timeout, 0, sizeof(*timeout));
- timeout->timeout = millis;
- h2o_linklist_init_anchor(&timeout->_entries);
-
- h2o_timeout__do_init(loop, timeout);
-}
-
-void h2o_timeout_dispose(h2o_loop_t *loop, h2o_timeout_t *timeout)
-{
- assert(h2o_linklist_is_empty(&timeout->_entries));
- h2o_timeout__do_dispose(loop, timeout);
-}
-
-void h2o_timeout_link(h2o_loop_t *loop, h2o_timeout_t *timeout, h2o_timeout_entry_t *entry)
-{
- /* insert at tail, so that the entries are sorted in ascending order */
- h2o_linklist_insert(&timeout->_entries, &entry->_link);
- /* set data */
- entry->registered_at = h2o_now(loop);
-
- h2o_timeout__do_link(loop, timeout, entry);
-}
-
-void h2o_timeout_unlink(h2o_timeout_entry_t *entry)
-{
- if (h2o_linklist_is_linked(&entry->_link)) {
- h2o_linklist_unlink(&entry->_link);
- entry->registered_at = 0;
- }
-}
diff --git a/web/server/h2o/libh2o/lib/common/url.c b/web/server/h2o/libh2o/lib/common/url.c
deleted file mode 100644
index d65d18fb5..000000000
--- a/web/server/h2o/libh2o/lib/common/url.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * Copyright (c) 2014,2015 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 <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include "h2o/memory.h"
-#include "h2o/string_.h"
-#include "h2o/url.h"
-
-const h2o_url_scheme_t H2O_URL_SCHEME_HTTP = {{H2O_STRLIT("http")}, 80};
-const h2o_url_scheme_t H2O_URL_SCHEME_HTTPS = {{H2O_STRLIT("https")}, 443};
-
-static int decode_hex(int ch)
-{
- if ('0' <= ch && ch <= '9')
- return ch - '0';
- if ('A' <= ch && ch <= 'F')
- return ch - 'A' + 0xa;
- if ('a' <= ch && ch <= 'f')
- return ch - 'a' + 0xa;
- return -1;
-}
-
-static size_t handle_special_paths(const char *path, size_t off, size_t last_slash)
-{
- size_t orig_off = off, part_size = off - last_slash;
-
- if (part_size == 2 && path[off - 1] == '.') {
- --off;
- } else if (part_size == 3 && path[off - 2] == '.' && path[off - 1] == '.') {
- off -= 2;
- if (off > 1) {
- for (--off; path[off - 1] != '/'; --off)
- ;
- }
- }
- return orig_off - off;
-}
-
-/* Perform path normalization and URL decoding in one pass.
- * See h2o_req_t for the purpose of @norm_indexes. */
-static h2o_iovec_t rebuild_path(h2o_mem_pool_t *pool, const char *src, size_t src_len, size_t *query_at, size_t **norm_indexes)
-{
- char *dst;
- size_t src_off = 0, dst_off = 0, last_slash, rewind;
-
- { /* locate '?', and set len to the end of input path */
- const char *q = memchr(src, '?', src_len);
- if (q != NULL) {
- src_len = *query_at = q - src;
- } else {
- *query_at = SIZE_MAX;
- }
- }
-
- /* dst can be 1 byte more than src if src is missing the prefixing '/' */
- dst = h2o_mem_alloc_pool(pool, src_len + 1);
- *norm_indexes = h2o_mem_alloc_pool(pool, (src_len + 1) * sizeof(*norm_indexes[0]));
-
- if (src[0] == '/')
- src_off++;
- last_slash = dst_off;
- dst[dst_off] = '/';
- (*norm_indexes)[dst_off] = src_off;
- dst_off++;
-
- /* decode %xx */
- while (src_off < src_len) {
- int hi, lo;
- char decoded;
-
- if (src[src_off] == '%' && (src_off + 2 < src_len) && (hi = decode_hex(src[src_off + 1])) != -1 &&
- (lo = decode_hex(src[src_off + 2])) != -1) {
- decoded = (hi << 4) | lo;
- src_off += 3;
- } else {
- decoded = src[src_off++];
- }
- if (decoded == '/') {
- rewind = handle_special_paths(dst, dst_off, last_slash);
- if (rewind > 0) {
- dst_off -= rewind;
- last_slash = dst_off - 1;
- continue;
- }
- last_slash = dst_off;
- }
- dst[dst_off] = decoded;
- (*norm_indexes)[dst_off] = src_off;
- dst_off++;
- }
- rewind = handle_special_paths(dst, dst_off, last_slash);
- dst_off -= rewind;
-
- return h2o_iovec_init(dst, dst_off);
-}
-
-h2o_iovec_t h2o_url_normalize_path(h2o_mem_pool_t *pool, const char *path, size_t len, size_t *query_at, size_t **norm_indexes)
-{
- const char *p = path, *end = path + len;
- h2o_iovec_t ret;
-
- *query_at = SIZE_MAX;
- *norm_indexes = NULL;
-
- if (len == 0) {
- ret = h2o_iovec_init("/", 1);
- return ret;
- }
-
- if (path[0] != '/')
- goto Rewrite;
-
- for (; p + 1 < end; ++p) {
- if ((p[0] == '/' && p[1] == '.') || p[0] == '%') {
- /* detect false positives as well */
- goto Rewrite;
- } else if (p[0] == '?') {
- *query_at = p - path;
- goto Return;
- }
- }
- for (; p < end; ++p) {
- if (p[0] == '?') {
- *query_at = p - path;
- goto Return;
- }
- }
-
-Return:
- ret.base = (char *)path;
- ret.len = p - path;
- return ret;
-
-Rewrite:
- ret = rebuild_path(pool, path, len, query_at, norm_indexes);
- if (ret.len == 0)
- goto RewriteError;
- if (ret.base[0] != '/')
- goto RewriteError;
- if (h2o_strstr(ret.base, ret.len, H2O_STRLIT("/../")) != SIZE_MAX)
- goto RewriteError;
- if (ret.len >= 3 && memcmp(ret.base + ret.len - 3, "/..", 3) == 0)
- goto RewriteError;
- return ret;
-RewriteError:
- fprintf(stderr, "failed to normalize path: `%.*s` => `%.*s`\n", (int)len, path, (int)ret.len, ret.base);
- ret = h2o_iovec_init("/", 1);
- return ret;
-}
-
-static const char *parse_scheme(const char *s, const char *end, const h2o_url_scheme_t **scheme)
-{
- if (end - s >= 5 && memcmp(s, "http:", 5) == 0) {
- *scheme = &H2O_URL_SCHEME_HTTP;
- return s + 5;
- } else if (end - s >= 6 && memcmp(s, "https:", 6) == 0) {
- *scheme = &H2O_URL_SCHEME_HTTPS;
- return s + 6;
- }
- return NULL;
-}
-
-const char *h2o_url_parse_hostport(const char *s, size_t len, h2o_iovec_t *host, uint16_t *port)
-{
- const char *token_start = s, *token_end, *end = s + len;
-
- *port = 65535;
-
- if (token_start == end)
- return NULL;
-
- if (*token_start == '[') {
- /* is IPv6 address */
- ++token_start;
- if ((token_end = memchr(token_start, ']', end - token_start)) == NULL)
- return NULL;
- *host = h2o_iovec_init(token_start, token_end - token_start);
- token_start = token_end + 1;
- } else {
- for (token_end = token_start; !(token_end == end || *token_end == '/' || *token_end == ':'); ++token_end)
- ;
- *host = h2o_iovec_init(token_start, token_end - token_start);
- token_start = token_end;
- }
-
- /* disallow zero-length host */
- if (host->len == 0)
- return NULL;
-
- /* parse port */
- if (token_start != end && *token_start == ':') {
- size_t p;
- ++token_start;
- if ((token_end = memchr(token_start, '/', end - token_start)) == NULL)
- token_end = end;
- if ((p = h2o_strtosize(token_start, token_end - token_start)) >= 65535)
- return NULL;
- *port = (uint16_t)p;
- token_start = token_end;
- }
-
- return token_start;
-}
-
-static int parse_authority_and_path(const char *src, const char *url_end, h2o_url_t *parsed)
-{
- const char *p = h2o_url_parse_hostport(src, url_end - src, &parsed->host, &parsed->_port);
- if (p == NULL)
- return -1;
- parsed->authority = h2o_iovec_init(src, p - src);
- if (p == url_end) {
- parsed->path = h2o_iovec_init(H2O_STRLIT("/"));
- } else {
- if (*p != '/')
- return -1;
- parsed->path = h2o_iovec_init(p, url_end - p);
- }
- return 0;
-}
-
-int h2o_url_parse(const char *url, size_t url_len, h2o_url_t *parsed)
-{
- const char *url_end, *p;
-
- if (url_len == SIZE_MAX)
- url_len = strlen(url);
- url_end = url + url_len;
-
- /* check and skip scheme */
- if ((p = parse_scheme(url, url_end, &parsed->scheme)) == NULL)
- return -1;
-
- /* skip "//" */
- if (!(url_end - p >= 2 && p[0] == '/' && p[1] == '/'))
- return -1;
- p += 2;
-
- return parse_authority_and_path(p, url_end, parsed);
-}
-
-int h2o_url_parse_relative(const char *url, size_t url_len, h2o_url_t *parsed)
-{
- const char *url_end, *p;
-
- if (url_len == SIZE_MAX)
- url_len = strlen(url);
- url_end = url + url_len;
-
- /* obtain scheme and port number */
- if ((p = parse_scheme(url, url_end, &parsed->scheme)) == NULL) {
- parsed->scheme = NULL;
- p = url;
- }
-
- /* handle "//" */
- if (url_end - p >= 2 && p[0] == '/' && p[1] == '/')
- return parse_authority_and_path(p + 2, url_end, parsed);
-
- /* reset authority, host, port, and set path */
- parsed->authority = (h2o_iovec_t){NULL};
- parsed->host = (h2o_iovec_t){NULL};
- parsed->_port = 65535;
- parsed->path = h2o_iovec_init(p, url_end - p);
-
- return 0;
-}
-
-h2o_iovec_t h2o_url_resolve(h2o_mem_pool_t *pool, const h2o_url_t *base, const h2o_url_t *relative, h2o_url_t *dest)
-{
- h2o_iovec_t base_path, relative_path, ret;
-
- assert(base->path.len != 0);
- assert(base->path.base[0] == '/');
-
- if (relative == NULL) {
- /* build URL using base copied to dest */
- *dest = *base;
- base_path = base->path;
- relative_path = h2o_iovec_init(NULL, 0);
- goto Build;
- }
-
- /* scheme */
- dest->scheme = relative->scheme != NULL ? relative->scheme : base->scheme;
-
- /* authority (and host:port) */
- if (relative->authority.base != NULL) {
- assert(relative->host.base != NULL);
- dest->authority = relative->authority;
- dest->host = relative->host;
- dest->_port = relative->_port;
- } else {
- assert(relative->host.base == NULL);
- assert(relative->_port == 65535);
- dest->authority = base->authority;
- dest->host = base->host;
- dest->_port = base->_port;
- }
-
- /* path */
- base_path = base->path;
- if (relative->path.base != NULL) {
- relative_path = relative->path;
- h2o_url_resolve_path(&base_path, &relative_path);
- } else {
- assert(relative->path.len == 0);
- relative_path = (h2o_iovec_t){NULL};
- }
-
-Build:
- /* build the output */
- ret = h2o_concat(pool, dest->scheme->name, h2o_iovec_init(H2O_STRLIT("://")), dest->authority, base_path, relative_path);
- /* adjust dest */
- dest->authority.base = ret.base + dest->scheme->name.len + 3;
- dest->host.base = dest->authority.base;
- if (dest->authority.len != 0 && dest->authority.base[0] == '[')
- ++dest->host.base;
- dest->path.base = dest->authority.base + dest->authority.len;
- dest->path.len = ret.base + ret.len - dest->path.base;
-
- return ret;
-}
-
-void h2o_url_resolve_path(h2o_iovec_t *base, h2o_iovec_t *relative)
-{
- size_t base_path_len = base->len, rel_path_offset = 0;
-
- if (relative->len != 0 && relative->base[0] == '/') {
- base_path_len = 0;
- } else {
- /* relative path */
- while (base->base[--base_path_len] != '/')
- ;
- while (rel_path_offset != relative->len) {
- if (relative->base[rel_path_offset] == '.') {
- if (relative->len - rel_path_offset >= 2 && relative->base[rel_path_offset + 1] == '.' &&
- (relative->len - rel_path_offset == 2 || relative->base[rel_path_offset + 2] == '/')) {
- if (base_path_len != 0) {
- while (base->base[--base_path_len] != '/')
- ;
- }
- rel_path_offset += relative->len - rel_path_offset == 2 ? 2 : 3;
- continue;
- }
- if (relative->len - rel_path_offset == 1) {
- rel_path_offset += 1;
- continue;
- } else if (relative->base[rel_path_offset + 1] == '/') {
- rel_path_offset += 2;
- continue;
- }
- }
- break;
- }
- base_path_len += 1;
- }
-
- base->len = base_path_len;
- *relative = h2o_iovec_init(relative->base + rel_path_offset, relative->len - rel_path_offset);
-}
-
-void h2o_url_copy(h2o_mem_pool_t *pool, h2o_url_t *dest, const h2o_url_t *src)
-{
- dest->scheme = src->scheme;
- dest->authority = h2o_strdup(pool, src->authority.base, src->authority.len);
- dest->host = h2o_strdup(pool, src->host.base, src->host.len);
- dest->path = h2o_strdup(pool, src->path.base, src->path.len);
- dest->_port = src->_port;
-}
-
-const char *h2o_url_host_to_sun(h2o_iovec_t host, struct sockaddr_un *sa)
-{
-#define PREFIX "unix:"
-
- if (host.len < sizeof(PREFIX) - 1 || memcmp(host.base, PREFIX, sizeof(PREFIX) - 1) != 0)
- return h2o_url_host_to_sun_err_is_not_unix_socket;
-
- if (host.len - sizeof(PREFIX) - 1 >= sizeof(sa->sun_path))
- return "unix-domain socket path is too long";
-
- memset(sa, 0, sizeof(*sa));
- sa->sun_family = AF_UNIX;
- memcpy(sa->sun_path, host.base + sizeof(PREFIX) - 1, host.len - (sizeof(PREFIX) - 1));
- return NULL;
-
-#undef PREFIX
-}
-
-const char *h2o_url_host_to_sun_err_is_not_unix_socket = "supplied name does not look like an unix-domain socket";
diff --git a/web/server/h2o/libh2o/lib/core/config.c b/web/server/h2o/libh2o/lib/core/config.c
deleted file mode 100644
index ce1d32018..000000000
--- a/web/server/h2o/libh2o/lib/core/config.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (c) 2014-2016 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 <inttypes.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "h2o.h"
-#include "h2o/configurator.h"
-#include "h2o/http1.h"
-#include "h2o/http2.h"
-
-static h2o_hostconf_t *create_hostconf(h2o_globalconf_t *globalconf)
-{
- h2o_hostconf_t *hostconf = h2o_mem_alloc(sizeof(*hostconf));
- *hostconf = (h2o_hostconf_t){globalconf};
- hostconf->http2.push_preload = 1; /* enabled by default */
- h2o_config_init_pathconf(&hostconf->fallback_path, globalconf, NULL, globalconf->mimemap);
- hostconf->mimemap = globalconf->mimemap;
- h2o_mem_addref_shared(hostconf->mimemap);
- return hostconf;
-}
-
-static void destroy_hostconf(h2o_hostconf_t *hostconf)
-{
- size_t i;
-
- if (hostconf->authority.hostport.base != hostconf->authority.host.base)
- free(hostconf->authority.hostport.base);
- free(hostconf->authority.host.base);
- for (i = 0; i != hostconf->paths.size; ++i) {
- h2o_pathconf_t *pathconf = hostconf->paths.entries + i;
- h2o_config_dispose_pathconf(pathconf);
- }
- free(hostconf->paths.entries);
- h2o_config_dispose_pathconf(&hostconf->fallback_path);
- h2o_mem_release_shared(hostconf->mimemap);
-
- free(hostconf);
-}
-
-static void on_dispose_envconf(void *_envconf)
-{
- h2o_envconf_t *envconf = _envconf;
- size_t i;
-
- if (envconf->parent != NULL)
- h2o_mem_release_shared(envconf->parent);
-
- for (i = 0; i != envconf->unsets.size; ++i)
- h2o_mem_release_shared(envconf->unsets.entries[i].base);
- free(envconf->unsets.entries);
- for (i = 0; i != envconf->sets.size; ++i)
- h2o_mem_release_shared(envconf->sets.entries[i].base);
- free(envconf->sets.entries);
-}
-
-h2o_envconf_t *h2o_config_create_envconf(h2o_envconf_t *parent)
-{
- h2o_envconf_t *envconf = h2o_mem_alloc_shared(NULL, sizeof(*envconf), on_dispose_envconf);
- *envconf = (h2o_envconf_t){NULL};
-
- if (parent != NULL) {
- envconf->parent = parent;
- h2o_mem_addref_shared(parent);
- }
- return envconf;
-}
-
-void h2o_config_setenv(h2o_envconf_t *envconf, const char *name, const char *value)
-{
- size_t name_len = strlen(name), i;
- h2o_iovec_t *value_slot;
-
- /* remove from the list of unsets */
- for (i = 0; i != envconf->unsets.size; ++i) {
- if (h2o_memis(envconf->unsets.entries[i].base, envconf->unsets.entries[i].len, name, name_len)) {
- h2o_mem_release_shared(envconf->unsets.entries[i].base);
- h2o_vector_erase(&envconf->unsets, i);
- break;
- }
- }
- /* find the slot */
- for (i = 0; i != envconf->sets.size; i += 2) {
- if (h2o_memis(envconf->sets.entries[i].base, envconf->sets.entries[i].len, name, name_len)) {
- value_slot = envconf->sets.entries + i + 1;
- h2o_mem_release_shared(value_slot->base);
- goto SetValue;
- }
- }
- /* name not found in existing sets */
- h2o_vector_reserve(NULL, &envconf->sets, envconf->sets.size + 2);
- envconf->sets.entries[envconf->sets.size++] = h2o_strdup_shared(NULL, name, name_len);
- value_slot = envconf->sets.entries + envconf->sets.size++;
-SetValue:
- *value_slot = h2o_strdup_shared(NULL, value, SIZE_MAX);
-}
-
-void h2o_config_unsetenv(h2o_envconf_t *envconf, const char *name)
-{
- size_t i, name_len = strlen(name);
-
- /* do nothing if already set */
- for (i = 0; i != envconf->unsets.size; ++i)
- if (h2o_memis(envconf->unsets.entries[i].base, envconf->unsets.entries[i].len, name, name_len))
- return;
- /* register */
- h2o_vector_reserve(NULL, &envconf->unsets, envconf->unsets.size + 1);
- envconf->unsets.entries[envconf->unsets.size++] = h2o_strdup_shared(NULL, name, name_len);
-}
-
-void h2o_config_init_pathconf(h2o_pathconf_t *pathconf, h2o_globalconf_t *globalconf, const char *path, h2o_mimemap_t *mimemap)
-{
- memset(pathconf, 0, sizeof(*pathconf));
- pathconf->global = globalconf;
- h2o_chunked_register(pathconf);
- if (path != NULL)
- pathconf->path = h2o_strdup(NULL, path, SIZE_MAX);
- h2o_mem_addref_shared(mimemap);
- pathconf->mimemap = mimemap;
- pathconf->error_log.emit_request_errors = 1;
-}
-
-void h2o_config_dispose_pathconf(h2o_pathconf_t *pathconf)
-{
-#define DESTROY_LIST(type, list) \
- do { \
- size_t i; \
- for (i = 0; i != list.size; ++i) { \
- type *e = list.entries[i]; \
- if (e->dispose != NULL) \
- e->dispose(e); \
- free(e); \
- } \
- free(list.entries); \
- } while (0)
- DESTROY_LIST(h2o_handler_t, pathconf->handlers);
- DESTROY_LIST(h2o_filter_t, pathconf->filters);
- DESTROY_LIST(h2o_logger_t, pathconf->loggers);
-#undef DESTROY_LIST
-
- free(pathconf->path.base);
- if (pathconf->mimemap != NULL)
- h2o_mem_release_shared(pathconf->mimemap);
- if (pathconf->env != NULL)
- h2o_mem_release_shared(pathconf->env);
-}
-
-void h2o_config_init(h2o_globalconf_t *config)
-{
- memset(config, 0, sizeof(*config));
- config->hosts = h2o_mem_alloc(sizeof(config->hosts[0]));
- config->hosts[0] = NULL;
- h2o_linklist_init_anchor(&config->configurators);
- config->server_name = h2o_iovec_init(H2O_STRLIT("h2o/" H2O_VERSION));
- config->max_request_entity_size = H2O_DEFAULT_MAX_REQUEST_ENTITY_SIZE;
- config->max_delegations = H2O_DEFAULT_MAX_DELEGATIONS;
- config->handshake_timeout = H2O_DEFAULT_HANDSHAKE_TIMEOUT;
- config->http1.req_timeout = H2O_DEFAULT_HTTP1_REQ_TIMEOUT;
- config->http1.upgrade_to_http2 = H2O_DEFAULT_HTTP1_UPGRADE_TO_HTTP2;
- config->http1.callbacks = H2O_HTTP1_CALLBACKS;
- config->http2.idle_timeout = H2O_DEFAULT_HTTP2_IDLE_TIMEOUT;
- config->http2.graceful_shutdown_timeout = H2O_DEFAULT_HTTP2_GRACEFUL_SHUTDOWN_TIMEOUT;
- config->proxy.io_timeout = H2O_DEFAULT_PROXY_IO_TIMEOUT;
- config->proxy.emit_x_forwarded_headers = 1;
- config->proxy.emit_via_header = 1;
- config->http2.max_concurrent_requests_per_connection = H2O_HTTP2_SETTINGS_HOST.max_concurrent_streams;
- config->http2.max_streams_for_priority = 16;
- config->http2.latency_optimization.min_rtt = 50; // milliseconds
- config->http2.latency_optimization.max_additional_delay = 10;
- config->http2.latency_optimization.max_cwnd = 65535;
- config->http2.callbacks = H2O_HTTP2_CALLBACKS;
- config->mimemap = h2o_mimemap_create();
-
- h2o_configurator__init_core(config);
-}
-
-h2o_pathconf_t *h2o_config_register_path(h2o_hostconf_t *hostconf, const char *path, int flags)
-{
- h2o_pathconf_t *pathconf;
-
- h2o_vector_reserve(NULL, &hostconf->paths, hostconf->paths.size + 1);
- pathconf = hostconf->paths.entries + hostconf->paths.size++;
-
- h2o_config_init_pathconf(pathconf, hostconf->global, path, hostconf->mimemap);
-
- return pathconf;
-}
-
-void h2o_config_register_status_handler(h2o_globalconf_t *config, h2o_status_handler_t status_handler)
-{
- h2o_vector_reserve(NULL, &config->statuses, config->statuses.size + 1);
- config->statuses.entries[config->statuses.size++] = status_handler;
-}
-
-void h2o_config_register_simple_status_handler(h2o_globalconf_t *config, h2o_iovec_t name, final_status_handler_cb status_handler)
-{
- h2o_status_handler_t *sh;
-
- h2o_vector_reserve(NULL, &config->statuses, config->statuses.size + 1);
- sh = &config->statuses.entries[config->statuses.size++];
- memset(sh, 0, sizeof(*sh));
- sh->name = h2o_strdup(NULL, name.base, name.len);
- sh->final = status_handler;
-}
-
-h2o_hostconf_t *h2o_config_register_host(h2o_globalconf_t *config, h2o_iovec_t host, uint16_t port)
-{
- h2o_hostconf_t *hostconf = NULL;
- h2o_iovec_t host_lc;
-
- assert(host.len != 0);
-
- /* convert hostname to lowercase */
- host_lc = h2o_strdup(NULL, host.base, host.len);
- h2o_strtolower(host_lc.base, host_lc.len);
-
- { /* return NULL if given authority is already registered */
- h2o_hostconf_t **p;
- for (p = config->hosts; *p != NULL; ++p)
- if (h2o_memis((*p)->authority.host.base, (*p)->authority.host.len, host_lc.base, host_lc.len) &&
- (*p)->authority.port == port)
- goto Exit;
- }
-
- /* create hostconf */
- hostconf = create_hostconf(config);
- hostconf->authority.host = host_lc;
- host_lc = (h2o_iovec_t){NULL};
- hostconf->authority.port = port;
- if (hostconf->authority.port == 65535) {
- hostconf->authority.hostport = hostconf->authority.host;
- } else {
- hostconf->authority.hostport.base = h2o_mem_alloc(hostconf->authority.host.len + sizeof("[]:" H2O_UINT16_LONGEST_STR));
- if (strchr(hostconf->authority.host.base, ':') != NULL) {
- hostconf->authority.hostport.len =
- sprintf(hostconf->authority.hostport.base, "[%s]:%" PRIu16, hostconf->authority.host.base, port);
- } else {
- hostconf->authority.hostport.len =
- sprintf(hostconf->authority.hostport.base, "%s:%" PRIu16, hostconf->authority.host.base, port);
- }
- }
-
- /* append to the list */
- h2o_append_to_null_terminated_list((void *)&config->hosts, hostconf);
-
-Exit:
- free(host_lc.base);
- return hostconf;
-}
-
-void h2o_config_dispose(h2o_globalconf_t *config)
-{
- size_t i;
-
- for (i = 0; config->hosts[i] != NULL; ++i) {
- h2o_hostconf_t *hostconf = config->hosts[i];
- destroy_hostconf(hostconf);
- }
- free(config->hosts);
-
- h2o_mem_release_shared(config->mimemap);
- h2o_configurator__dispose_configurators(config);
-}
-
-h2o_handler_t *h2o_create_handler(h2o_pathconf_t *conf, size_t sz)
-{
- h2o_handler_t *handler = h2o_mem_alloc(sz);
-
- memset(handler, 0, sz);
- handler->_config_slot = conf->global->_num_config_slots++;
-
- h2o_vector_reserve(NULL, &conf->handlers, conf->handlers.size + 1);
- conf->handlers.entries[conf->handlers.size++] = handler;
-
- return handler;
-}
-
-h2o_filter_t *h2o_create_filter(h2o_pathconf_t *conf, size_t sz)
-{
- h2o_filter_t *filter = h2o_mem_alloc(sz);
-
- memset(filter, 0, sz);
- filter->_config_slot = conf->global->_num_config_slots++;
-
- h2o_vector_reserve(NULL, &conf->filters, conf->filters.size + 1);
- memmove(conf->filters.entries + 1, conf->filters.entries, conf->filters.size * sizeof(conf->filters.entries[0]));
- conf->filters.entries[0] = filter;
- ++conf->filters.size;
-
- return filter;
-}
-
-h2o_logger_t *h2o_create_logger(h2o_pathconf_t *conf, size_t sz)
-{
- h2o_logger_t *logger = h2o_mem_alloc(sz);
-
- memset(logger, 0, sz);
- logger->_config_slot = conf->global->_num_config_slots++;
-
- h2o_vector_reserve(NULL, &conf->loggers, conf->loggers.size + 1);
- conf->loggers.entries[conf->loggers.size++] = logger;
-
- return logger;
-}
diff --git a/web/server/h2o/libh2o/lib/core/configurator.c b/web/server/h2o/libh2o/lib/core/configurator.c
deleted file mode 100644
index 891770cc2..000000000
--- a/web/server/h2o/libh2o/lib/core/configurator.c
+++ /dev/null
@@ -1,1102 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Fastly, Inc.
- *
- * 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 <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include "h2o.h"
-#include "h2o/configurator.h"
-
-struct st_core_config_vars_t {
- struct {
- unsigned reprioritize_blocking_assets : 1;
- unsigned push_preload : 1;
- h2o_casper_conf_t casper;
- } http2;
- struct {
- unsigned emit_request_errors : 1;
- } error_log;
-};
-
-struct st_core_configurator_t {
- h2o_configurator_t super;
- struct st_core_config_vars_t *vars, _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static h2o_configurator_context_t *create_context(h2o_configurator_context_t *parent, int is_custom_handler)
-{
- h2o_configurator_context_t *ctx = h2o_mem_alloc(sizeof(*ctx));
- if (parent == NULL) {
- *ctx = (h2o_configurator_context_t){NULL};
- return ctx;
- }
- *ctx = *parent;
- if (ctx->env != NULL)
- h2o_mem_addref_shared(ctx->env);
- ctx->parent = parent;
- return ctx;
-}
-
-static void destroy_context(h2o_configurator_context_t *ctx)
-{
- if (ctx->env != NULL) {
- if (ctx->pathconf != NULL)
- ctx->pathconf->env = ctx->env;
- else
- h2o_mem_release_shared(ctx->env);
- }
- free(ctx);
-}
-
-static int on_core_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_core_configurator_t *self = (void *)_self;
-
- ++self->vars;
- self->vars[0] = self->vars[-1];
- return 0;
-}
-
-static int on_core_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_core_configurator_t *self = (void *)_self;
-
- if (ctx->hostconf != NULL && ctx->pathconf == NULL) {
- /* exitting from host-level configuration */
- ctx->hostconf->http2.reprioritize_blocking_assets = self->vars->http2.reprioritize_blocking_assets;
- ctx->hostconf->http2.push_preload = self->vars->http2.push_preload;
- ctx->hostconf->http2.casper = self->vars->http2.casper;
- } else if (ctx->pathconf != NULL) {
- /* exitting from path or extension-level configuration */
- ctx->pathconf->error_log.emit_request_errors = self->vars->error_log.emit_request_errors;
- }
-
- --self->vars;
- return 0;
-}
-
-static void destroy_configurator(h2o_configurator_t *configurator)
-{
- if (configurator->dispose != NULL)
- configurator->dispose(configurator);
- free(configurator->commands.entries);
- free(configurator);
-}
-
-static int setup_configurators(h2o_configurator_context_t *ctx, int is_enter, yoml_t *node)
-{
- h2o_linklist_t *n;
-
- for (n = ctx->globalconf->configurators.next; n != &ctx->globalconf->configurators; n = n->next) {
- h2o_configurator_t *c = H2O_STRUCT_FROM_MEMBER(h2o_configurator_t, _link, n);
- if (is_enter) {
- if (c->enter != NULL && c->enter(c, ctx, node) != 0)
- return -1;
- } else {
- if (c->exit != NULL && c->exit(c, ctx, node) != 0)
- return -1;
- }
- }
-
- return 0;
-}
-
-static int config_timeout(h2o_configurator_command_t *cmd, yoml_t *node, uint64_t *slot)
-{
- uint64_t timeout_in_secs;
-
- if (h2o_configurator_scanf(cmd, node, "%" SCNu64, &timeout_in_secs) != 0)
- return -1;
-
- *slot = timeout_in_secs * 1000;
- return 0;
-}
-
-int h2o_configurator_apply_commands(h2o_configurator_context_t *ctx, yoml_t *node, int flags_mask, const char **ignore_commands)
-{
- struct st_cmd_value_t {
- h2o_configurator_command_t *cmd;
- yoml_t *value;
- };
- H2O_VECTOR(struct st_cmd_value_t) deferred = {NULL}, semi_deferred = {NULL};
- int ret = -1;
-
- if (node != NULL && node->type != YOML_TYPE_MAPPING) {
- h2o_configurator_errprintf(NULL, node, "node must be a MAPPING");
- goto Exit;
- }
-
- /* call on_enter of every configurator */
- if (setup_configurators(ctx, 1, node) != 0)
- goto Exit;
-
- /* handle the configuration commands */
- if (node != NULL) {
- size_t i;
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key, *value = node->data.mapping.elements[i].value;
- h2o_configurator_command_t *cmd;
- /* obtain the target command */
- if (key->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(NULL, key, "command must be a string");
- goto Exit;
- }
- if (ignore_commands != NULL) {
- size_t i;
- for (i = 0; ignore_commands[i] != NULL; ++i)
- if (strcmp(ignore_commands[i], key->data.scalar) == 0)
- goto SkipCommand;
- }
- if ((cmd = h2o_configurator_get_command(ctx->globalconf, key->data.scalar)) == NULL) {
- h2o_configurator_errprintf(NULL, key, "unknown command: %s", key->data.scalar);
- goto Exit;
- }
- if ((cmd->flags & flags_mask) == 0) {
- h2o_configurator_errprintf(cmd, key, "the command cannot be used at this level");
- goto Exit;
- }
- /* check value type */
- if ((cmd->flags & (H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR | H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE |
- H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING)) != 0) {
- switch (value->type) {
- case YOML_TYPE_SCALAR:
- if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR) == 0) {
- h2o_configurator_errprintf(cmd, value, "argument cannot be a scalar");
- goto Exit;
- }
- break;
- case YOML_TYPE_SEQUENCE:
- if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE) == 0) {
- h2o_configurator_errprintf(cmd, value, "argument cannot be a sequence");
- goto Exit;
- }
- break;
- case YOML_TYPE_MAPPING:
- if ((cmd->flags & H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING) == 0) {
- h2o_configurator_errprintf(cmd, value, "argument cannot be a mapping");
- goto Exit;
- }
- break;
- default:
- assert(!"unreachable");
- break;
- }
- }
- /* handle the command (or keep it for later execution) */
- if ((cmd->flags & H2O_CONFIGURATOR_FLAG_SEMI_DEFERRED) != 0) {
- h2o_vector_reserve(NULL, &semi_deferred, semi_deferred.size + 1);
- semi_deferred.entries[semi_deferred.size++] = (struct st_cmd_value_t){cmd, value};
- } else if ((cmd->flags & H2O_CONFIGURATOR_FLAG_DEFERRED) != 0) {
- h2o_vector_reserve(NULL, &deferred, deferred.size + 1);
- deferred.entries[deferred.size++] = (struct st_cmd_value_t){cmd, value};
- } else {
- if (cmd->cb(cmd, ctx, value) != 0)
- goto Exit;
- }
- SkipCommand:;
- }
- for (i = 0; i != semi_deferred.size; ++i) {
- struct st_cmd_value_t *pair = semi_deferred.entries + i;
- if (pair->cmd->cb(pair->cmd, ctx, pair->value) != 0)
- goto Exit;
- }
- for (i = 0; i != deferred.size; ++i) {
- struct st_cmd_value_t *pair = deferred.entries + i;
- if (pair->cmd->cb(pair->cmd, ctx, pair->value) != 0)
- goto Exit;
- }
- }
-
- /* call on_exit of every configurator */
- if (setup_configurators(ctx, 0, node) != 0)
- goto Exit;
-
- ret = 0;
-Exit:
- free(deferred.entries);
- free(semi_deferred.entries);
- return ret;
-}
-
-static int sort_from_longer_paths(const yoml_mapping_element_t *x, const yoml_mapping_element_t *y)
-{
- size_t xlen = strlen(x->key->data.scalar), ylen = strlen(y->key->data.scalar);
- if (xlen < ylen)
- return 1;
- else if (xlen > ylen)
- return -1;
- /* apply strcmp for stable sort */
- return strcmp(x->key->data.scalar, y->key->data.scalar);
-}
-
-static yoml_t *convert_path_config_node(h2o_configurator_command_t *cmd, yoml_t *node)
-{
- size_t i, j;
-
- switch (node->type) {
- case YOML_TYPE_MAPPING:
- break;
- case YOML_TYPE_SEQUENCE: {
- /* convert to mapping */
- yoml_t *map = h2o_mem_alloc(sizeof(yoml_t));
- *map = (yoml_t){YOML_TYPE_MAPPING};
- if (node->filename != NULL)
- map->filename = h2o_strdup(NULL, node->filename, SIZE_MAX).base;
- map->line = node->line;
- map->column = node->column;
- if (node->anchor != NULL)
- map->anchor = h2o_strdup(NULL, node->anchor, SIZE_MAX).base;
- map->_refcnt = 1;
-
- for (i = 0; i != node->data.sequence.size; ++i) {
- yoml_t *elem = node->data.sequence.elements[i];
- if (elem->type != YOML_TYPE_MAPPING) {
- yoml_free(map, NULL);
- goto Error;
- }
- for (j = 0; j != elem->data.mapping.size; ++j) {
- yoml_t *elemkey = elem->data.mapping.elements[j].key;
- yoml_t *elemvalue = elem->data.mapping.elements[j].value;
- map = h2o_mem_realloc(map, offsetof(yoml_t, data.mapping.elements) +
- sizeof(yoml_mapping_element_t) * (map->data.mapping.size + 1));
- map->data.mapping.elements[map->data.mapping.size].key = elemkey;
- map->data.mapping.elements[map->data.mapping.size].value = elemvalue;
- ++map->data.mapping.size;
- ++elemkey->_refcnt;
- ++elemvalue->_refcnt;
- }
- }
- return map;
- } break;
- default:
- Error:
- h2o_configurator_errprintf(cmd, node, "value must be a mapping or sequence of mapping");
- return NULL;
- }
-
- ++node->_refcnt;
- return node;
-}
-
-static int config_path(h2o_configurator_context_t *parent_ctx, h2o_pathconf_t *pathconf, yoml_t *node)
-{
- h2o_configurator_context_t *path_ctx = create_context(parent_ctx, 0);
- path_ctx->pathconf = pathconf;
- path_ctx->mimemap = &pathconf->mimemap;
-
- int ret = h2o_configurator_apply_commands(path_ctx, node, H2O_CONFIGURATOR_FLAG_PATH, NULL);
-
- destroy_context(path_ctx);
- return ret;
-}
-
-static int on_config_paths(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- size_t i;
-
- /* sort by the length of the path (descending) */
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key;
- if (key->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, key, "key (representing the virtual path) must be a string");
- return -1;
- }
- }
- qsort(node->data.mapping.elements, node->data.mapping.size, sizeof(node->data.mapping.elements[0]),
- (int (*)(const void *, const void *))sort_from_longer_paths);
-
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key, *value;
- if ((value = convert_path_config_node(cmd, node->data.mapping.elements[i].value)) == NULL)
- return -1;
- h2o_pathconf_t *pathconf = h2o_config_register_path(ctx->hostconf, key->data.scalar, 0);
- int cmd_ret = config_path(ctx, pathconf, value);
- yoml_free(value, NULL);
- if (cmd_ret != 0)
- return cmd_ret;
- }
-
- /* configure fallback path along with ordinary paths */
- return config_path(ctx, &ctx->hostconf->fallback_path, NULL);
-}
-
-static int on_config_hosts(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- size_t i;
-
- if (node->data.mapping.size == 0) {
- h2o_configurator_errprintf(cmd, node, "the mapping cannot be empty");
- return -1;
- }
-
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key;
- yoml_t *value = node->data.mapping.elements[i].value;
- h2o_iovec_t hostname;
- uint16_t port;
- if (key->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, key, "key (representing the hostname) must be a string");
- return -1;
- }
- if (h2o_url_parse_hostport(key->data.scalar, strlen(key->data.scalar), &hostname, &port) == NULL) {
- h2o_configurator_errprintf(cmd, key, "invalid key (must be either `host` or `host:port`)");
- return -1;
- }
- assert(hostname.len != 0);
- if ((hostname.base[0] == '*' && !(hostname.len == 1 || hostname.base[1] == '.')) ||
- memchr(hostname.base + 1, '*', hostname.len - 1) != NULL) {
- h2o_configurator_errprintf(cmd, key, "wildcard (*) can only be used at the start of the hostname");
- return -1;
- }
- h2o_configurator_context_t *host_ctx = create_context(ctx, 0);
- if ((host_ctx->hostconf = h2o_config_register_host(host_ctx->globalconf, hostname, port)) == NULL) {
- h2o_configurator_errprintf(cmd, key, "duplicate host entry");
- destroy_context(host_ctx);
- return -1;
- }
- host_ctx->mimemap = &host_ctx->hostconf->mimemap;
- int cmd_ret = h2o_configurator_apply_commands(host_ctx, value, H2O_CONFIGURATOR_FLAG_HOST, NULL);
- destroy_context(host_ctx);
- if (cmd_ret != 0)
- return -1;
- if (yoml_get(value, "paths") == NULL) {
- h2o_configurator_errprintf(NULL, value, "mandatory configuration directive `paths` is missing");
- return -1;
- }
- }
-
- return 0;
-}
-
-static int on_config_limit_request_body(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return h2o_configurator_scanf(cmd, node, "%zu", &ctx->globalconf->max_request_entity_size);
-}
-
-static int on_config_max_delegations(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return h2o_configurator_scanf(cmd, node, "%u", &ctx->globalconf->max_delegations);
-}
-
-static int on_config_handshake_timeout(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return config_timeout(cmd, node, &ctx->globalconf->handshake_timeout);
-}
-
-static int on_config_http1_request_timeout(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return config_timeout(cmd, node, &ctx->globalconf->http1.req_timeout);
-}
-
-static int on_config_http1_upgrade_to_http2(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
- if (ret == -1)
- return -1;
- ctx->globalconf->http1.upgrade_to_http2 = (int)ret;
- return 0;
-}
-
-static int on_config_http2_idle_timeout(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return config_timeout(cmd, node, &ctx->globalconf->http2.idle_timeout);
-}
-
-static int on_config_http2_graceful_shutdown_timeout(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- return config_timeout(cmd, node, &ctx->globalconf->http2.graceful_shutdown_timeout);
-}
-
-static int on_config_http2_max_concurrent_requests_per_connection(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx,
- yoml_t *node)
-{
- return h2o_configurator_scanf(cmd, node, "%zu", &ctx->globalconf->http2.max_concurrent_requests_per_connection);
-}
-
-static int on_config_http2_latency_optimization_min_rtt(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx,
- yoml_t *node)
-{
- return h2o_configurator_scanf(cmd, node, "%u", &ctx->globalconf->http2.latency_optimization.min_rtt);
-}
-
-static int on_config_http2_latency_optimization_max_additional_delay(h2o_configurator_command_t *cmd,
- h2o_configurator_context_t *ctx, yoml_t *node)
-{
- double ratio;
- if (h2o_configurator_scanf(cmd, node, "%lf", &ratio) != 0)
- return -1;
- if (!(0.0 < ratio)) {
- h2o_configurator_errprintf(cmd, node, "ratio must be a positive number");
- return -1;
- }
- ctx->globalconf->http2.latency_optimization.max_additional_delay = 100 * ratio;
- return 0;
-}
-
-static int on_config_http2_latency_optimization_max_cwnd(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx,
- yoml_t *node)
-{
- return h2o_configurator_scanf(cmd, node, "%u", &ctx->globalconf->http2.latency_optimization.max_cwnd);
-}
-
-static int on_config_http2_reprioritize_blocking_assets(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx,
- yoml_t *node)
-{
- struct st_core_configurator_t *self = (void *)cmd->configurator;
- ssize_t on;
-
- if ((on = h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
- return -1;
- self->vars->http2.reprioritize_blocking_assets = (int)on;
-
- return 0;
-}
-
-static int on_config_http2_push_preload(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_core_configurator_t *self = (void *)cmd->configurator;
- ssize_t on;
-
- if ((on = h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
- return -1;
- self->vars->http2.push_preload = (int)on;
-
- return 0;
-}
-
-static int on_config_http2_casper(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- static const h2o_casper_conf_t defaults = {
- 13, /* casper_bits: default (2^13 ~= 100 assets * 1/0.01 collision probability) */
- 0 /* track blocking assets only */
- };
-
- struct st_core_configurator_t *self = (void *)cmd->configurator;
-
- switch (node->type) {
- case YOML_TYPE_SCALAR:
- if (strcasecmp(node->data.scalar, "OFF") == 0) {
- self->vars->http2.casper = (h2o_casper_conf_t){0};
- } else if (strcasecmp(node->data.scalar, "ON") == 0) {
- self->vars->http2.casper = defaults;
- }
- break;
- case YOML_TYPE_MAPPING: {
- /* set to default */
- self->vars->http2.casper = defaults;
- /* override the attributes defined */
- yoml_t *t;
- if ((t = yoml_get(node, "capacity-bits")) != NULL) {
- if (!(t->type == YOML_TYPE_SCALAR && sscanf(t->data.scalar, "%u", &self->vars->http2.casper.capacity_bits) == 1 &&
- self->vars->http2.casper.capacity_bits < 16)) {
- h2o_configurator_errprintf(cmd, t, "value of `capacity-bits` must be an integer between 0 to 15");
- return -1;
- }
- }
- if ((t = yoml_get(node, "tracking-types")) != NULL) {
- if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "blocking-assets") == 0) {
- self->vars->http2.casper.track_all_types = 0;
- } else if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "all") == 0) {
- self->vars->http2.casper.track_all_types = 1;
- } else {
- h2o_configurator_errprintf(cmd, t, "value of `tracking-types` must be either of: `blocking-assets` or `all`");
- return -1;
- }
- }
- } break;
- default:
- h2o_configurator_errprintf(cmd, node, "value must be `OFF`,`ON` or a mapping containing the necessary attributes");
- return -1;
- }
-
- return 0;
-}
-
-static int assert_is_mimetype(h2o_configurator_command_t *cmd, yoml_t *node)
-{
- if (node->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, node, "expected a scalar (mime-type)");
- return -1;
- }
- if (strchr(node->data.scalar, '/') == NULL) {
- h2o_configurator_errprintf(cmd, node, "the string \"%s\" does not look like a mime-type", node->data.scalar);
- return -1;
- }
- return 0;
-}
-
-static int assert_is_extension(h2o_configurator_command_t *cmd, yoml_t *node)
-{
- if (node->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, node, "expected a scalar (extension)");
- return -1;
- }
- if (node->data.scalar[0] != '.') {
- h2o_configurator_errprintf(cmd, node, "given extension \"%s\" does not start with a \".\"", node->data.scalar);
- return -1;
- }
- return 0;
-}
-
-static int set_mimetypes(h2o_configurator_command_t *cmd, h2o_mimemap_t *mimemap, yoml_t *node)
-{
- size_t i, j;
-
- assert(node->type == YOML_TYPE_MAPPING);
-
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key;
- yoml_t *value = node->data.mapping.elements[i].value;
- if (assert_is_mimetype(cmd, key) != 0)
- return -1;
- switch (value->type) {
- case YOML_TYPE_SCALAR:
- if (assert_is_extension(cmd, value) != 0)
- return -1;
- h2o_mimemap_define_mimetype(mimemap, value->data.scalar + 1, key->data.scalar, NULL);
- break;
- case YOML_TYPE_SEQUENCE:
- for (j = 0; j != value->data.sequence.size; ++j) {
- yoml_t *ext_node = value->data.sequence.elements[j];
- if (assert_is_extension(cmd, ext_node) != 0)
- return -1;
- h2o_mimemap_define_mimetype(mimemap, ext_node->data.scalar + 1, key->data.scalar, NULL);
- }
- break;
- case YOML_TYPE_MAPPING: {
- yoml_t *t;
- h2o_mime_attributes_t attr;
- h2o_mimemap_get_default_attributes(key->data.scalar, &attr);
- if ((t = yoml_get(value, "is_compressible")) != NULL) {
- if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "YES") == 0) {
- attr.is_compressible = 1;
- } else if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "NO") == 0) {
- attr.is_compressible = 0;
- } else {
- h2o_configurator_errprintf(cmd, t, "`is_compressible` attribute must be either of: `YES` or `NO`");
- return -1;
- }
- }
- if ((t = yoml_get(value, "priority")) != NULL) {
- if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "normal") == 0) {
- attr.priority = H2O_MIME_ATTRIBUTE_PRIORITY_NORMAL;
- } else if (t->type == YOML_TYPE_SCALAR && strcasecmp(t->data.scalar, "highest") == 0) {
- attr.priority = H2O_MIME_ATTRIBUTE_PRIORITY_HIGHEST;
- } else {
- h2o_configurator_errprintf(cmd, t, "`priority` attribute must be either of: `normal` or `highest`");
- return -1;
- }
- }
- if ((t = yoml_get(value, "extensions")) == NULL) {
- h2o_configurator_errprintf(cmd, value, "cannot find mandatory attribute `extensions`");
- return -1;
- }
- if (t->type != YOML_TYPE_SEQUENCE) {
- h2o_configurator_errprintf(cmd, t, "`extensions` attribute must be a sequence of scalars");
- return -1;
- }
- for (j = 0; j != t->data.sequence.size; ++j) {
- yoml_t *ext_node = t->data.sequence.elements[j];
- if (assert_is_extension(cmd, ext_node) != 0)
- return -1;
- h2o_mimemap_define_mimetype(mimemap, ext_node->data.scalar + 1, key->data.scalar, &attr);
- }
- } break;
- default:
- fprintf(stderr, "logic flaw at %s:%d\n", __FILE__, __LINE__);
- abort();
- }
- }
-
- return 0;
-}
-
-static int on_config_mime_settypes(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- h2o_mimemap_t *newmap = h2o_mimemap_create();
- h2o_mimemap_clear_types(newmap);
- h2o_mimemap_set_default_type(newmap, h2o_mimemap_get_default_type(*ctx->mimemap)->data.mimetype.base, NULL);
- if (set_mimetypes(cmd, newmap, node) != 0) {
- h2o_mem_release_shared(newmap);
- return -1;
- }
-
- h2o_mem_release_shared(*ctx->mimemap);
- *ctx->mimemap = newmap;
- return 0;
-}
-
-static void clone_mimemap_if_clean(h2o_configurator_context_t *ctx)
-{
- if (ctx->parent == NULL)
- return;
- if (*ctx->mimemap != *ctx->parent->mimemap)
- return;
- h2o_mem_release_shared(*ctx->mimemap);
- /* even after release, ctx->mimemap is still retained by the parent and therefore we can use it as the argument to clone */
- *ctx->mimemap = h2o_mimemap_clone(*ctx->mimemap);
-}
-
-static int on_config_mime_addtypes(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- clone_mimemap_if_clean(ctx);
- return set_mimetypes(cmd, *ctx->mimemap, node);
-}
-
-static int on_config_mime_removetypes(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- size_t i;
-
- clone_mimemap_if_clean(ctx);
- for (i = 0; i != node->data.sequence.size; ++i) {
- yoml_t *ext_node = node->data.sequence.elements[i];
- if (assert_is_extension(cmd, ext_node) != 0)
- return -1;
- h2o_mimemap_remove_type(*ctx->mimemap, ext_node->data.scalar + 1);
- }
-
- return 0;
-}
-
-static int on_config_mime_setdefaulttype(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- if (assert_is_mimetype(cmd, node) != 0)
- return -1;
-
- clone_mimemap_if_clean(ctx);
- h2o_mimemap_set_default_type(*ctx->mimemap, node->data.scalar, NULL);
-
- return 0;
-}
-
-static int on_config_custom_handler(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- static const char *ignore_commands[] = {"extension", NULL};
- yoml_t *ext_node;
- const char **exts;
- h2o_mimemap_type_t *type = NULL;
-
- if (node->type != YOML_TYPE_MAPPING) {
- h2o_configurator_errprintf(cmd, node, "argument must be a MAPPING");
- return -1;
- }
- if ((ext_node = yoml_get(node, "extension")) == NULL) {
- h2o_configurator_errprintf(cmd, node, "mandatory key `extension` is missing");
- return -1;
- }
-
- /* create dynamic type */
- switch (ext_node->type) {
- case YOML_TYPE_SCALAR:
- if (assert_is_extension(cmd, ext_node) != 0)
- return -1;
- exts = alloca(2 * sizeof(*exts));
- exts[0] = ext_node->data.scalar + 1;
- exts[1] = NULL;
- break;
- case YOML_TYPE_SEQUENCE: {
- exts = alloca((ext_node->data.sequence.size + 1) * sizeof(*exts));
- size_t i;
- for (i = 0; i != ext_node->data.sequence.size; ++i) {
- yoml_t *n = ext_node->data.sequence.elements[i];
- if (assert_is_extension(cmd, n) != 0)
- return -1;
- exts[i] = n->data.scalar + 1;
- }
- exts[i] = NULL;
- } break;
- default:
- h2o_configurator_errprintf(cmd, ext_node, "`extensions` must be a scalar or sequence of scalar");
- return -1;
- }
- clone_mimemap_if_clean(ctx);
- type = h2o_mimemap_define_dynamic(*ctx->mimemap, exts, ctx->globalconf);
-
- /* apply the configuration commands */
- h2o_configurator_context_t *ext_ctx = create_context(ctx, 1);
- ext_ctx->pathconf = &type->data.dynamic.pathconf;
- ext_ctx->mimemap = NULL;
- int cmd_ret = h2o_configurator_apply_commands(ext_ctx, node, H2O_CONFIGURATOR_FLAG_EXTENSION, ignore_commands);
- destroy_context(ext_ctx);
- if (cmd_ret != 0)
- return cmd_ret;
- switch (type->data.dynamic.pathconf.handlers.size) {
- case 1:
- break;
- case 0:
- h2o_configurator_errprintf(cmd, node, "no handler declared for given extension");
- return -1;
- default:
- h2o_configurator_errprintf(cmd, node, "cannot assign more than one handler for given extension");
- return -1;
- }
-
- return 0;
-}
-
-static void inherit_env_if_necessary(h2o_configurator_context_t *ctx)
-{
- if (ctx->env == (ctx->parent != NULL ? ctx->parent->env : NULL))
- ctx->env = h2o_config_create_envconf(ctx->env);
-}
-
-static int on_config_setenv(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- size_t i;
-
- inherit_env_if_necessary(ctx);
-
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key, *value = node->data.mapping.elements[i].value;
- if (key->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, key, "key must be a scalar");
- return -1;
- }
- if (value->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, value, "value must be a scalar");
- return -1;
- }
- h2o_config_setenv(ctx->env, key->data.scalar, value->data.scalar);
- }
-
- return 0;
-}
-
-static int on_config_unsetenv(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- inherit_env_if_necessary(ctx);
-
- switch (node->type) {
- case YOML_TYPE_SCALAR:
- h2o_config_unsetenv(ctx->env, node->data.scalar);
- break;
- case YOML_TYPE_SEQUENCE: {
- size_t i;
- for (i = 0; i != node->data.sequence.size; ++i) {
- yoml_t *element = node->data.sequence.elements[i];
- if (element->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, element, "element of a sequence passed to unsetenv must be a scalar");
- return -1;
- }
- h2o_config_unsetenv(ctx->env, element->data.scalar);
- }
- } break;
- default:
- h2o_configurator_errprintf(cmd, node, "argument to unsetenv must be either a scalar or a sequence");
- return -1;
- }
-
- return 0;
-}
-
-static int on_config_server_name(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- ctx->globalconf->server_name = h2o_strdup(NULL, node->data.scalar, SIZE_MAX);
- return 0;
-}
-
-static int on_config_send_server_name(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- switch(h2o_configurator_get_one_of(cmd, node, "OFF,ON,preserve")) {
- case 0: /* off */
- ctx->globalconf->server_name = h2o_iovec_init(H2O_STRLIT(""));
- break;
- case 1: /* on */
- break;
- case 2: /* preserve */
- ctx->globalconf->server_name = h2o_iovec_init(H2O_STRLIT(""));
- ctx->globalconf->proxy.preserve_server_header = 1;
- break;
- default:
- return -1;
- }
- return 0;
-}
-
-static int on_config_error_log_emit_request_errors(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_core_configurator_t *self = (void *)cmd->configurator;
- ssize_t on;
-
- if ((on = h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
- return -1;
-
- self->vars->error_log.emit_request_errors = (int)on;
- return 0;
-}
-
-void h2o_configurator__init_core(h2o_globalconf_t *conf)
-{
- /* check if already initialized */
- if (h2o_configurator_get_command(conf, "files") != NULL)
- return;
-
- { /* `hosts` and `paths` */
- h2o_configurator_t *c = h2o_configurator_create(conf, sizeof(*c));
- h2o_configurator_define_command(c, "hosts", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING |
- H2O_CONFIGURATOR_FLAG_DEFERRED,
- on_config_hosts);
- h2o_configurator_define_command(c, "paths", H2O_CONFIGURATOR_FLAG_HOST | H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING |
- H2O_CONFIGURATOR_FLAG_DEFERRED,
- on_config_paths);
- };
-
- { /* setup global configurators */
- struct st_core_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
- c->super.enter = on_core_enter;
- c->super.exit = on_core_exit;
- c->vars = c->_vars_stack;
- c->vars->http2.reprioritize_blocking_assets = 1; /* defaults to ON */
- c->vars->http2.push_preload = 1; /* defaults to ON */
- c->vars->error_log.emit_request_errors = 1; /* defaults to ON */
- h2o_configurator_define_command(&c->super, "limit-request-body",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_limit_request_body);
- h2o_configurator_define_command(&c->super, "max-delegations",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_max_delegations);
- h2o_configurator_define_command(&c->super, "handshake-timeout",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_handshake_timeout);
- h2o_configurator_define_command(&c->super, "http1-request-timeout",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http1_request_timeout);
- h2o_configurator_define_command(&c->super, "http1-upgrade-to-http2",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http1_upgrade_to_http2);
- h2o_configurator_define_command(&c->super, "http2-idle-timeout",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_idle_timeout);
- h2o_configurator_define_command(&c->super, "http2-graceful-shutdown-timeout",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_graceful_shutdown_timeout);
- h2o_configurator_define_command(&c->super, "http2-max-concurrent-requests-per-connection",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_max_concurrent_requests_per_connection);
- h2o_configurator_define_command(&c->super, "http2-latency-optimization-min-rtt",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_latency_optimization_min_rtt);
- h2o_configurator_define_command(&c->super, "http2-latency-optimization-max-additional-delay",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_latency_optimization_max_additional_delay);
- h2o_configurator_define_command(&c->super, "http2-latency-optimization-max-cwnd",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_latency_optimization_max_cwnd);
- h2o_configurator_define_command(&c->super, "http2-reprioritize-blocking-assets",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_HOST |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_reprioritize_blocking_assets);
- h2o_configurator_define_command(&c->super, "http2-push-preload", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_HOST |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_http2_push_preload);
- h2o_configurator_define_command(&c->super, "http2-casper", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_HOST,
- on_config_http2_casper);
- h2o_configurator_define_command(&c->super, "file.mime.settypes",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING,
- on_config_mime_settypes);
- h2o_configurator_define_command(&c->super, "file.mime.addtypes",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING,
- on_config_mime_addtypes);
- h2o_configurator_define_command(&c->super, "file.mime.removetypes",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE,
- on_config_mime_removetypes);
- h2o_configurator_define_command(&c->super, "file.mime.setdefaulttype",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_mime_setdefaulttype);
- h2o_configurator_define_command(&c->super, "file.custom-handler",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_SEMI_DEFERRED,
- on_config_custom_handler);
- h2o_configurator_define_command(&c->super, "setenv",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING, on_config_setenv);
- h2o_configurator_define_command(&c->super, "unsetenv", H2O_CONFIGURATOR_FLAG_ALL_LEVELS, on_config_unsetenv);
- h2o_configurator_define_command(&c->super, "server-name",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_server_name);
- h2o_configurator_define_command(&c->super, "send-server-name",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR |
- H2O_CONFIGURATOR_FLAG_DEFERRED,
- on_config_send_server_name);
- h2o_configurator_define_command(&c->super, "error-log.emit-request-errors",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_error_log_emit_request_errors);
- }
-}
-
-void h2o_configurator__dispose_configurators(h2o_globalconf_t *conf)
-{
- while (!h2o_linklist_is_empty(&conf->configurators)) {
- h2o_configurator_t *c = H2O_STRUCT_FROM_MEMBER(h2o_configurator_t, _link, conf->configurators.next);
- h2o_linklist_unlink(&c->_link);
- if (c->dispose != NULL)
- c->dispose(c);
- destroy_configurator(c);
- }
-}
-
-h2o_configurator_t *h2o_configurator_create(h2o_globalconf_t *conf, size_t sz)
-{
- h2o_configurator_t *c;
-
- assert(sz >= sizeof(*c));
-
- c = h2o_mem_alloc(sz);
- memset(c, 0, sz);
- h2o_linklist_insert(&conf->configurators, &c->_link);
-
- return c;
-}
-
-void h2o_configurator_define_command(h2o_configurator_t *configurator, const char *name, int flags, h2o_configurator_command_cb cb)
-{
- h2o_configurator_command_t *cmd;
-
- h2o_vector_reserve(NULL, &configurator->commands, configurator->commands.size + 1);
- cmd = configurator->commands.entries + configurator->commands.size++;
- cmd->configurator = configurator;
- cmd->flags = flags;
- cmd->name = name;
- cmd->cb = cb;
-}
-
-h2o_configurator_command_t *h2o_configurator_get_command(h2o_globalconf_t *conf, const char *name)
-{
- h2o_linklist_t *node;
- size_t i;
-
- for (node = conf->configurators.next; node != &conf->configurators; node = node->next) {
- h2o_configurator_t *configurator = H2O_STRUCT_FROM_MEMBER(h2o_configurator_t, _link, node);
- for (i = 0; i != configurator->commands.size; ++i) {
- h2o_configurator_command_t *cmd = configurator->commands.entries + i;
- if (strcmp(cmd->name, name) == 0) {
- return cmd;
- }
- }
- }
-
- return NULL;
-}
-
-int h2o_configurator_apply(h2o_globalconf_t *config, yoml_t *node, int dry_run)
-{
- h2o_configurator_context_t *ctx = create_context(NULL, 0);
- ctx->globalconf = config;
- ctx->mimemap = &ctx->globalconf->mimemap;
- ctx->dry_run = dry_run;
- int cmd_ret = h2o_configurator_apply_commands(ctx, node, H2O_CONFIGURATOR_FLAG_GLOBAL, NULL);
- destroy_context(ctx);
-
- if (cmd_ret != 0)
- return cmd_ret;
- if (config->hosts[0] == NULL) {
- h2o_configurator_errprintf(NULL, node, "mandatory configuration directive `hosts` is missing");
- return -1;
- }
- return 0;
-}
-
-void h2o_configurator_errprintf(h2o_configurator_command_t *cmd, yoml_t *node, const char *reason, ...)
-{
- va_list args;
-
- fprintf(stderr, "[%s:%zu] ", node->filename ? node->filename : "-", node->line + 1);
- if (cmd != NULL)
- fprintf(stderr, "in command %s, ", cmd->name);
- va_start(args, reason);
- vfprintf(stderr, reason, args);
- va_end(args);
- fputc('\n', stderr);
-}
-
-int h2o_configurator_scanf(h2o_configurator_command_t *cmd, yoml_t *node, const char *fmt, ...)
-{
- va_list args;
- int sscan_ret;
-
- if (node->type != YOML_TYPE_SCALAR)
- goto Error;
- va_start(args, fmt);
- sscan_ret = vsscanf(node->data.scalar, fmt, args);
- va_end(args);
- if (sscan_ret != 1)
- goto Error;
-
- return 0;
-Error:
- h2o_configurator_errprintf(cmd, node, "argument must match the format: %s", fmt);
- return -1;
-}
-
-ssize_t h2o_configurator_get_one_of(h2o_configurator_command_t *cmd, yoml_t *node, const char *candidates)
-{
- const char *config_str, *cand_str;
- ssize_t config_str_len, cand_index;
-
- if (node->type != YOML_TYPE_SCALAR)
- goto Error;
-
- config_str = node->data.scalar;
- config_str_len = strlen(config_str);
-
- cand_str = candidates;
- for (cand_index = 0;; ++cand_index) {
- if (strncasecmp(cand_str, config_str, config_str_len) == 0 &&
- (cand_str[config_str_len] == '\0' || cand_str[config_str_len] == ',')) {
- /* found */
- return cand_index;
- }
- cand_str = strchr(cand_str, ',');
- if (cand_str == NULL)
- goto Error;
- cand_str += 1; /* skip ',' */
- }
-/* not reached */
-
-Error:
- h2o_configurator_errprintf(cmd, node, "argument must be one of: %s", candidates);
- return -1;
-}
-
-char *h2o_configurator_get_cmd_path(const char *cmd)
-{
- char *root, *cmd_fullpath;
-
- /* just return the cmd (being strdup'ed) in case we do not need to prefix the value */
- if (cmd[0] == '/' || strchr(cmd, '/') == NULL)
- goto ReturnOrig;
-
- /* obtain root */
- if ((root = getenv("H2O_ROOT")) == NULL) {
- root = H2O_TO_STR(H2O_ROOT);
- }
-
- /* build full-path and return */
- cmd_fullpath = h2o_mem_alloc(strlen(root) + strlen(cmd) + 2);
- sprintf(cmd_fullpath, "%s/%s", root, cmd);
- return cmd_fullpath;
-
-ReturnOrig:
- return h2o_strdup(NULL, cmd, SIZE_MAX).base;
-}
diff --git a/web/server/h2o/libh2o/lib/core/context.c b/web/server/h2o/libh2o/lib/core/context.c
deleted file mode 100644
index 8d1101381..000000000
--- a/web/server/h2o/libh2o/lib/core/context.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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 <stddef.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include "h2o.h"
-#include "h2o/memcached.h"
-
-void h2o_context_init_pathconf_context(h2o_context_t *ctx, h2o_pathconf_t *pathconf)
-{
- /* add pathconf to the inited list (or return if already inited) */
- size_t i;
- for (i = 0; i != ctx->_pathconfs_inited.size; ++i)
- if (ctx->_pathconfs_inited.entries[i] == pathconf)
- return;
- h2o_vector_reserve(NULL, &ctx->_pathconfs_inited, ctx->_pathconfs_inited.size + 1);
- ctx->_pathconfs_inited.entries[ctx->_pathconfs_inited.size++] = pathconf;
-
-#define DOIT(type, list) \
- do { \
- size_t i; \
- for (i = 0; i != pathconf->list.size; ++i) { \
- type *o = pathconf->list.entries[i]; \
- if (o->on_context_init != NULL) \
- o->on_context_init(o, ctx); \
- } \
- } while (0)
-
- DOIT(h2o_handler_t, handlers);
- DOIT(h2o_filter_t, filters);
- DOIT(h2o_logger_t, loggers);
-
-#undef DOIT
-}
-
-void h2o_context_dispose_pathconf_context(h2o_context_t *ctx, h2o_pathconf_t *pathconf)
-{
- /* nullify pathconf in the inited list (or return if already disposed) */
- size_t i;
- for (i = 0; i != ctx->_pathconfs_inited.size; ++i)
- if (ctx->_pathconfs_inited.entries[i] == pathconf)
- break;
- if (i == ctx->_pathconfs_inited.size)
- return;
- ctx->_pathconfs_inited.entries[i] = NULL;
-
-#define DOIT(type, list) \
- do { \
- size_t i; \
- for (i = 0; i != pathconf->list.size; ++i) { \
- type *o = pathconf->list.entries[i]; \
- if (o->on_context_dispose != NULL) \
- o->on_context_dispose(o, ctx); \
- } \
- } while (0)
-
- DOIT(h2o_handler_t, handlers);
- DOIT(h2o_filter_t, filters);
- DOIT(h2o_logger_t, loggers);
-
-#undef DOIT
-}
-
-void h2o_context_init(h2o_context_t *ctx, h2o_loop_t *loop, h2o_globalconf_t *config)
-{
- size_t i, j;
-
- assert(config->hosts[0] != NULL);
-
- memset(ctx, 0, sizeof(*ctx));
- ctx->loop = loop;
- ctx->globalconf = config;
- h2o_timeout_init(ctx->loop, &ctx->zero_timeout, 0);
- h2o_timeout_init(ctx->loop, &ctx->one_sec_timeout, 1000);
- h2o_timeout_init(ctx->loop, &ctx->hundred_ms_timeout, 100);
- ctx->queue = h2o_multithread_create_queue(loop);
- h2o_multithread_register_receiver(ctx->queue, &ctx->receivers.hostinfo_getaddr, h2o_hostinfo_getaddr_receiver);
- ctx->filecache = h2o_filecache_create(config->filecache.capacity);
-
- h2o_timeout_init(ctx->loop, &ctx->handshake_timeout, config->handshake_timeout);
- h2o_timeout_init(ctx->loop, &ctx->http1.req_timeout, config->http1.req_timeout);
- h2o_linklist_init_anchor(&ctx->http1._conns);
- h2o_timeout_init(ctx->loop, &ctx->http2.idle_timeout, config->http2.idle_timeout);
- h2o_timeout_init(ctx->loop, &ctx->http2.graceful_shutdown_timeout, config->http2.graceful_shutdown_timeout);
- h2o_linklist_init_anchor(&ctx->http2._conns);
- ctx->proxy.client_ctx.loop = loop;
- h2o_timeout_init(ctx->loop, &ctx->proxy.io_timeout, config->proxy.io_timeout);
- ctx->proxy.client_ctx.getaddr_receiver = &ctx->receivers.hostinfo_getaddr;
- ctx->proxy.client_ctx.io_timeout = &ctx->proxy.io_timeout;
- ctx->proxy.client_ctx.ssl_ctx = config->proxy.ssl_ctx;
-
- ctx->_module_configs = h2o_mem_alloc(sizeof(*ctx->_module_configs) * config->_num_config_slots);
- memset(ctx->_module_configs, 0, sizeof(*ctx->_module_configs) * config->_num_config_slots);
-
- static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- pthread_mutex_lock(&mutex);
- for (i = 0; config->hosts[i] != NULL; ++i) {
- h2o_hostconf_t *hostconf = config->hosts[i];
- for (j = 0; j != hostconf->paths.size; ++j) {
- h2o_pathconf_t *pathconf = hostconf->paths.entries + j;
- h2o_context_init_pathconf_context(ctx, pathconf);
- }
- h2o_context_init_pathconf_context(ctx, &hostconf->fallback_path);
- }
- pthread_mutex_unlock(&mutex);
-}
-
-void h2o_context_dispose(h2o_context_t *ctx)
-{
- h2o_globalconf_t *config = ctx->globalconf;
- size_t i, j;
-
- for (i = 0; config->hosts[i] != NULL; ++i) {
- h2o_hostconf_t *hostconf = config->hosts[i];
- for (j = 0; j != hostconf->paths.size; ++j) {
- h2o_pathconf_t *pathconf = hostconf->paths.entries + j;
- h2o_context_dispose_pathconf_context(ctx, pathconf);
- }
- h2o_context_dispose_pathconf_context(ctx, &hostconf->fallback_path);
- }
- free(ctx->_pathconfs_inited.entries);
- free(ctx->_module_configs);
- h2o_timeout_dispose(ctx->loop, &ctx->zero_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->one_sec_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->hundred_ms_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->handshake_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->http1.req_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->http2.idle_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->http2.graceful_shutdown_timeout);
- h2o_timeout_dispose(ctx->loop, &ctx->proxy.io_timeout);
- /* what should we do here? assert(!h2o_linklist_is_empty(&ctx->http2._conns); */
-
- h2o_filecache_destroy(ctx->filecache);
- ctx->filecache = NULL;
-
- /* clear storage */
- for (i = 0; i != ctx->storage.size; ++i) {
- h2o_context_storage_item_t *item = ctx->storage.entries + i;
- if (item->dispose != NULL) {
- item->dispose(item->data);
- }
- }
- free(ctx->storage.entries);
-
- /* TODO assert that the all the getaddrinfo threads are idle */
- h2o_multithread_unregister_receiver(ctx->queue, &ctx->receivers.hostinfo_getaddr);
- h2o_multithread_destroy_queue(ctx->queue);
-
- if (ctx->_timestamp_cache.value != NULL)
- h2o_mem_release_shared(ctx->_timestamp_cache.value);
-
-#if H2O_USE_LIBUV
- /* make sure the handles released by h2o_timeout_dispose get freed */
- uv_run(ctx->loop, UV_RUN_NOWAIT);
-#endif
-}
-
-void h2o_context_request_shutdown(h2o_context_t *ctx)
-{
- ctx->shutdown_requested = 1;
- if (ctx->globalconf->http1.callbacks.request_shutdown != NULL)
- ctx->globalconf->http1.callbacks.request_shutdown(ctx);
- if (ctx->globalconf->http2.callbacks.request_shutdown != NULL)
- ctx->globalconf->http2.callbacks.request_shutdown(ctx);
-}
-
-void h2o_context_update_timestamp_cache(h2o_context_t *ctx)
-{
- time_t prev_sec = ctx->_timestamp_cache.tv_at.tv_sec;
- ctx->_timestamp_cache.uv_now_at = h2o_now(ctx->loop);
- gettimeofday(&ctx->_timestamp_cache.tv_at, NULL);
- if (ctx->_timestamp_cache.tv_at.tv_sec != prev_sec) {
- struct tm gmt;
- /* update the string cache */
- if (ctx->_timestamp_cache.value != NULL)
- h2o_mem_release_shared(ctx->_timestamp_cache.value);
- ctx->_timestamp_cache.value = h2o_mem_alloc_shared(NULL, sizeof(h2o_timestamp_string_t), NULL);
- gmtime_r(&ctx->_timestamp_cache.tv_at.tv_sec, &gmt);
- h2o_time2str_rfc1123(ctx->_timestamp_cache.value->rfc1123, &gmt);
- h2o_time2str_log(ctx->_timestamp_cache.value->log, ctx->_timestamp_cache.tv_at.tv_sec);
- }
-}
diff --git a/web/server/h2o/libh2o/lib/core/headers.c b/web/server/h2o/libh2o/lib/core/headers.c
deleted file mode 100644
index d31183623..000000000
--- a/web/server/h2o/libh2o/lib/core/headers.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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 <stddef.h>
-#include <stdio.h>
-#include "h2o.h"
-
-static void add_header(h2o_mem_pool_t *pool, h2o_headers_t *headers, h2o_iovec_t *name, const char *orig_name, const char *value,
- size_t value_len)
-{
- h2o_header_t *slot;
-
- h2o_vector_reserve(pool, headers, headers->size + 1);
- slot = headers->entries + headers->size++;
-
- slot->name = name;
- slot->value.base = (char *)value;
- slot->value.len = value_len;
- slot->orig_name = orig_name ? h2o_strdup(pool, orig_name, name->len).base : NULL;
-}
-
-ssize_t h2o_find_header(const h2o_headers_t *headers, const h2o_token_t *token, ssize_t cursor)
-{
- for (++cursor; cursor < headers->size; ++cursor) {
- if (headers->entries[cursor].name == &token->buf) {
- return cursor;
- }
- }
- return -1;
-}
-
-ssize_t h2o_find_header_by_str(const h2o_headers_t *headers, const char *name, size_t name_len, ssize_t cursor)
-{
- for (++cursor; cursor < headers->size; ++cursor) {
- h2o_header_t *t = headers->entries + cursor;
- if (h2o_memis(t->name->base, t->name->len, name, name_len)) {
- return cursor;
- }
- }
- return -1;
-}
-
-void h2o_add_header(h2o_mem_pool_t *pool, h2o_headers_t *headers, const h2o_token_t *token, const char *orig_name,
- const char *value, size_t value_len)
-{
- add_header(pool, headers, (h2o_iovec_t *)&token->buf, orig_name, value, value_len);
-}
-
-void h2o_add_header_by_str(h2o_mem_pool_t *pool, h2o_headers_t *headers, const char *name, size_t name_len, int maybe_token,
- const char *orig_name, const char *value, size_t value_len)
-{
- h2o_iovec_t *name_buf;
-
- if (maybe_token) {
- const h2o_token_t *token = h2o_lookup_token(name, name_len);
- if (token != NULL) {
- add_header(pool, headers, (h2o_iovec_t *)token, orig_name, value, value_len);
- return;
- }
- }
- name_buf = h2o_mem_alloc_pool(pool, sizeof(h2o_iovec_t));
- name_buf->base = (char *)name;
- name_buf->len = name_len;
- add_header(pool, headers, name_buf, orig_name, value, value_len);
-}
-
-void h2o_set_header(h2o_mem_pool_t *pool, h2o_headers_t *headers, const h2o_token_t *token, const char *value, size_t value_len,
- int overwrite_if_exists)
-{
- ssize_t cursor = h2o_find_header(headers, token, -1);
- if (cursor != -1) {
- if (overwrite_if_exists) {
- h2o_iovec_t *slot = &headers->entries[cursor].value;
- slot->base = (char *)value;
- slot->len = value_len;
- }
- } else {
- h2o_add_header(pool, headers, token, NULL, value, value_len);
- }
-}
-
-void h2o_set_header_by_str(h2o_mem_pool_t *pool, h2o_headers_t *headers, const char *name, size_t name_len, int maybe_token,
- const char *value, size_t value_len, int overwrite_if_exists)
-{
- ssize_t cursor;
-
- if (maybe_token) {
- const h2o_token_t *token = h2o_lookup_token(name, name_len);
- if (token != NULL) {
- h2o_set_header(pool, headers, token, value, value_len, overwrite_if_exists);
- return;
- }
- }
-
- cursor = h2o_find_header_by_str(headers, name, name_len, -1);
- if (cursor != -1) {
- if (overwrite_if_exists) {
- h2o_iovec_t *slot = &headers->entries[cursor].value;
- slot->base = (char *)value;
- slot->len = value_len;
- }
- } else {
- h2o_iovec_t *name_buf = h2o_mem_alloc_pool(pool, sizeof(h2o_iovec_t));
- name_buf->base = (char *)name;
- name_buf->len = name_len;
- add_header(pool, headers, name_buf, NULL, value, value_len);
- }
-}
-
-void h2o_set_header_token(h2o_mem_pool_t *pool, h2o_headers_t *headers, const h2o_token_t *token, const char *value,
- size_t value_len)
-{
- h2o_header_t *dest = NULL;
- size_t i;
- for (i = 0; i != headers->size; ++i) {
- if (headers->entries[i].name == &token->buf) {
- if (h2o_contains_token(headers->entries[i].value.base, headers->entries[i].value.len, value, value_len, ','))
- return;
- dest = headers->entries + i;
- }
- }
- if (dest != NULL) {
- dest->value = h2o_concat(pool, dest->value, h2o_iovec_init(H2O_STRLIT(", ")), h2o_iovec_init(value, value_len));
- } else {
- h2o_add_header(pool, headers, token, NULL, value, value_len);
- }
-}
-
-ssize_t h2o_delete_header(h2o_headers_t *headers, ssize_t cursor)
-{
- assert(cursor != -1);
-
- --headers->size;
- memmove(headers->entries + cursor, headers->entries + cursor + 1, sizeof(h2o_header_t) * (headers->size - cursor));
-
- return cursor;
-}
diff --git a/web/server/h2o/libh2o/lib/core/logconf.c b/web/server/h2o/libh2o/lib/core/logconf.c
deleted file mode 100644
index 4d79736cc..000000000
--- a/web/server/h2o/libh2o/lib/core/logconf.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "h2o.h"
-
-enum {
- ELEMENT_TYPE_EMPTY, /* empty element (with suffix only) */
- ELEMENT_TYPE_LOCAL_ADDR, /* %A */
- ELEMENT_TYPE_BYTES_SENT, /* %b */
- ELEMENT_TYPE_PROTOCOL, /* %H */
- ELEMENT_TYPE_REMOTE_ADDR, /* %h */
- ELEMENT_TYPE_LOGNAME, /* %l */
- ELEMENT_TYPE_METHOD, /* %m */
- ELEMENT_TYPE_LOCAL_PORT, /* %p, %{local}p */
- ELEMENT_TYPE_REMOTE_PORT, /* %{remote}p */
- ELEMENT_TYPE_ENV_VAR, /* %{..}e */
- ELEMENT_TYPE_QUERY, /* %q */
- ELEMENT_TYPE_REQUEST_LINE, /* %r */
- ELEMENT_TYPE_STATUS, /* %s */
- ELEMENT_TYPE_TIMESTAMP, /* %t */
- ELEMENT_TYPE_TIMESTAMP_STRFTIME, /* %{...}t */
- ELEMENT_TYPE_TIMESTAMP_SEC_SINCE_EPOCH, /* %{sec}t */
- ELEMENT_TYPE_TIMESTAMP_MSEC_SINCE_EPOCH, /* %{msec}t */
- ELEMENT_TYPE_TIMESTAMP_USEC_SINCE_EPOCH, /* %{usec}t */
- ELEMENT_TYPE_TIMESTAMP_MSEC_FRAC, /* %{msec_frac}t */
- ELEMENT_TYPE_TIMESTAMP_USEC_FRAC, /* %{usec_frac}t */
- ELEMENT_TYPE_URL_PATH, /* %U */
- ELEMENT_TYPE_REMOTE_USER, /* %u */
- ELEMENT_TYPE_AUTHORITY, /* %V */
- ELEMENT_TYPE_HOSTCONF, /* %v */
- ELEMENT_TYPE_IN_HEADER_TOKEN, /* %{data.header_token}i */
- ELEMENT_TYPE_IN_HEADER_STRING, /* %{data.name}i */
- ELEMENT_TYPE_OUT_HEADER_TOKEN, /* %{data.header_token}o */
- ELEMENT_TYPE_OUT_HEADER_STRING, /* %{data.name}o */
- ELEMENT_TYPE_OUT_HEADER_TOKEN_CONCATENATED, /* %{data.header_token}o */
- ELEMENT_TYPE_EXTENDED_VAR, /* %{data.name}x */
- ELEMENT_TYPE_CONNECTION_ID, /* %{connection-id}x */
- ELEMENT_TYPE_CONNECT_TIME, /* %{connect-time}x */
- ELEMENT_TYPE_REQUEST_HEADER_TIME, /* %{request-header-time}x */
- ELEMENT_TYPE_REQUEST_BODY_TIME, /* %{request-body-time}x */
- ELEMENT_TYPE_REQUEST_TOTAL_TIME, /* %{request-total-time}x */
- ELEMENT_TYPE_PROCESS_TIME, /* %{process-time}x */
- ELEMENT_TYPE_RESPONSE_TIME, /* %{response-total-time}x */
- ELEMENT_TYPE_DURATION, /* %{duration}x */
- ELEMENT_TYPE_ERROR, /* %{error}x */
- ELEMENT_TYPE_PROTOCOL_SPECIFIC, /* %{protocol-specific...}x */
- NUM_ELEMENT_TYPES
-};
-
-struct log_element_t {
- unsigned type;
- h2o_iovec_t suffix;
- union {
- const h2o_token_t *header_token;
- h2o_iovec_t name;
- size_t protocol_specific_callback_index;
- } data;
- unsigned magically_quoted_json : 1; /* whether to omit surrounding doublequotes when the output is null */
- unsigned original_response : 1;
-};
-
-struct st_h2o_logconf_t {
- H2O_VECTOR(struct log_element_t) elements;
- int escape;
-};
-
-static h2o_iovec_t strdup_lowercased(const char *s, size_t len)
-{
- h2o_iovec_t v = h2o_strdup(NULL, s, len);
- h2o_strtolower(v.base, v.len);
- return v;
-}
-
-static int determine_magicquote_nodes(h2o_logconf_t *logconf, char *errbuf)
-{
- size_t element_index;
- int quote_char = '\0'; /* the quote char being used if the state machine is within a string literal */
- int just_in = 0; /* if we just went into the string literal */
-
- for (element_index = 0; element_index < logconf->elements.size; ++element_index) {
- h2o_iovec_t suffix = logconf->elements.entries[element_index].suffix;
- logconf->elements.entries[element_index].magically_quoted_json = just_in && suffix.len != 0 && suffix.base[0] == quote_char;
-
- just_in = 0;
-
- size_t i;
- for (i = 0; i < suffix.len; ++i) {
- just_in = 0;
- if (quote_char != '\0') {
- if (quote_char == suffix.base[i]) {
- /* out of quote? */
- size_t j, num_bs = 0;
- for (j = i; j != 0; ++num_bs)
- if (suffix.base[--j] != '\\')
- break;
- if (num_bs % 2 == 0)
- quote_char = '\0';
- }
- } else {
- if (suffix.base[i] == '"' || suffix.base[i] == '\'') {
- quote_char = suffix.base[i];
- just_in = 1;
- }
- }
- }
- }
-
- return 1;
-}
-
-h2o_logconf_t *h2o_logconf_compile(const char *fmt, int escape, char *errbuf)
-{
- h2o_logconf_t *logconf = h2o_mem_alloc(sizeof(*logconf));
- const char *pt = fmt;
- size_t fmt_len = strlen(fmt);
-
- *logconf = (h2o_logconf_t){{NULL}, escape};
-
-#define LAST_ELEMENT() (logconf->elements.entries + logconf->elements.size - 1)
-/* suffix buffer is always guaranteed to be larger than the fmt + (sizeof('\n') - 1) (so that they would be no buffer overruns) */
-#define NEW_ELEMENT(ty) \
- do { \
- h2o_vector_reserve(NULL, &logconf->elements, logconf->elements.size + 1); \
- logconf->elements.size++; \
- *LAST_ELEMENT() = (struct log_element_t){0}; \
- LAST_ELEMENT()->type = ty; \
- LAST_ELEMENT()->suffix.base = h2o_mem_alloc(fmt_len + 1); \
- } while (0)
-
- while (*pt != '\0') {
- if (memcmp(pt, "%%", 2) == 0) {
- ++pt; /* emit % */
- } else if (*pt == '%') {
- ++pt;
- /* handle < and > */
- int log_original = 0;
- for (;; ++pt) {
- if (*pt == '<') {
- log_original = 1;
- } else if (*pt == '>') {
- log_original = 0;
- } else {
- break;
- }
- }
- /* handle {...}n */
- if (*pt == '{') {
- const h2o_token_t *token;
- const char *quote_end = strchr(++pt, '}');
- if (quote_end == NULL) {
- sprintf(errbuf, "failed to compile log format: unterminated header name starting at: \"%16s\"", pt);
- goto Error;
- }
- const char modifier = quote_end[1];
- switch (modifier) {
- case 'i':
- case 'o': {
- h2o_iovec_t name = strdup_lowercased(pt, quote_end - pt);
- token = h2o_lookup_token(name.base, name.len);
- if (token != NULL) {
- free(name.base);
- if (modifier == 'o' && token == H2O_TOKEN_SET_COOKIE) {
- NEW_ELEMENT(ELEMENT_TYPE_OUT_HEADER_TOKEN_CONCATENATED);
- LAST_ELEMENT()->data.header_token = token;
- } else {
- NEW_ELEMENT(modifier == 'i' ? ELEMENT_TYPE_IN_HEADER_TOKEN : ELEMENT_TYPE_OUT_HEADER_TOKEN);
- LAST_ELEMENT()->data.header_token = token;
- }
- } else {
- NEW_ELEMENT(modifier == 'i' ? ELEMENT_TYPE_IN_HEADER_STRING : ELEMENT_TYPE_OUT_HEADER_STRING);
- LAST_ELEMENT()->data.name = name;
- }
- LAST_ELEMENT()->original_response = log_original;
- } break;
- case 'p':
- if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("local"))) {
- NEW_ELEMENT(ELEMENT_TYPE_LOCAL_PORT);
- } else if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("remote"))) {
- NEW_ELEMENT(ELEMENT_TYPE_REMOTE_PORT);
- } else {
- sprintf(errbuf, "failed to compile log format: unknown specifier for %%{...}p");
- goto Error;
- }
- break;
- case 'e':
- {
- h2o_iovec_t name = h2o_strdup(NULL, pt, quote_end - pt);
- NEW_ELEMENT(ELEMENT_TYPE_ENV_VAR);
- LAST_ELEMENT()->data.name = name;
- }
- break;
- case 't':
- if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("sec"))) {
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_SEC_SINCE_EPOCH);
- } else if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("msec"))) {
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_MSEC_SINCE_EPOCH);
- } else if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("usec"))) {
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_USEC_SINCE_EPOCH);
- } else if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("msec_frac"))) {
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_MSEC_FRAC);
- } else if (h2o_memis(pt, quote_end - pt, H2O_STRLIT("usec_frac"))) {
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_USEC_FRAC);
- } else {
- h2o_iovec_t name = h2o_strdup(NULL, pt, quote_end - pt);
- NEW_ELEMENT(ELEMENT_TYPE_TIMESTAMP_STRFTIME);
- LAST_ELEMENT()->data.name = name;
- }
- break;
- case 'x':
-#define MAP_EXT_TO_TYPE(name, id) \
- if (h2o_lcstris(pt, quote_end - pt, H2O_STRLIT(name))) { \
- NEW_ELEMENT(id); \
- goto MAP_EXT_Found; \
- }
-#define MAP_EXT_TO_PROTO(name, cb) \
- if (h2o_lcstris(pt, quote_end - pt, H2O_STRLIT(name))) { \
- h2o_conn_callbacks_t dummy_; \
- NEW_ELEMENT(ELEMENT_TYPE_PROTOCOL_SPECIFIC); \
- LAST_ELEMENT()->data.protocol_specific_callback_index = \
- &dummy_.log_.cb - dummy_.log_.callbacks; \
- goto MAP_EXT_Found; \
- }
- MAP_EXT_TO_TYPE("connection-id", ELEMENT_TYPE_CONNECTION_ID);
- MAP_EXT_TO_TYPE("connect-time", ELEMENT_TYPE_CONNECT_TIME);
- MAP_EXT_TO_TYPE("request-total-time", ELEMENT_TYPE_REQUEST_TOTAL_TIME);
- MAP_EXT_TO_TYPE("request-header-time", ELEMENT_TYPE_REQUEST_HEADER_TIME);
- MAP_EXT_TO_TYPE("request-body-time", ELEMENT_TYPE_REQUEST_BODY_TIME);
- MAP_EXT_TO_TYPE("process-time", ELEMENT_TYPE_PROCESS_TIME);
- MAP_EXT_TO_TYPE("response-time", ELEMENT_TYPE_RESPONSE_TIME);
- MAP_EXT_TO_TYPE("duration", ELEMENT_TYPE_DURATION);
- MAP_EXT_TO_TYPE("error", ELEMENT_TYPE_ERROR);
- MAP_EXT_TO_PROTO("http1.request-index", http1.request_index);
- MAP_EXT_TO_PROTO("http2.stream-id", http2.stream_id);
- MAP_EXT_TO_PROTO("http2.priority.received", http2.priority_received);
- MAP_EXT_TO_PROTO("http2.priority.received.exclusive", http2.priority_received_exclusive);
- MAP_EXT_TO_PROTO("http2.priority.received.parent", http2.priority_received_parent);
- MAP_EXT_TO_PROTO("http2.priority.received.weight", http2.priority_received_weight);
- MAP_EXT_TO_PROTO("http2.priority.actual", http2.priority_actual);
- MAP_EXT_TO_PROTO("http2.priority.actual.parent", http2.priority_actual_parent);
- MAP_EXT_TO_PROTO("http2.priority.actual.weight", http2.priority_actual_weight);
- MAP_EXT_TO_PROTO("ssl.protocol-version", ssl.protocol_version);
- MAP_EXT_TO_PROTO("ssl.session-reused", ssl.session_reused);
- MAP_EXT_TO_PROTO("ssl.cipher", ssl.cipher);
- MAP_EXT_TO_PROTO("ssl.cipher-bits", ssl.cipher_bits);
- MAP_EXT_TO_PROTO("ssl.session-id", ssl.session_id);
- { /* not found */
- h2o_iovec_t name = strdup_lowercased(pt, quote_end - pt);
- NEW_ELEMENT(ELEMENT_TYPE_EXTENDED_VAR);
- LAST_ELEMENT()->data.name = name;
- }
- MAP_EXT_Found:
-#undef MAP_EXT_TO_TYPE
-#undef MAP_EXT_TO_PROTO
- break;
- default:
- sprintf(errbuf, "failed to compile log format: header name is not followed by either `i`, `o`, `x`, `e`");
- goto Error;
- }
- pt = quote_end + 2;
- continue;
- } else {
- unsigned type = NUM_ELEMENT_TYPES;
- switch (*pt++) {
-#define TYPE_MAP(ch, ty) \
- case ch: \
- type = ty; \
- break
- TYPE_MAP('A', ELEMENT_TYPE_LOCAL_ADDR);
- TYPE_MAP('b', ELEMENT_TYPE_BYTES_SENT);
- TYPE_MAP('H', ELEMENT_TYPE_PROTOCOL);
- TYPE_MAP('h', ELEMENT_TYPE_REMOTE_ADDR);
- TYPE_MAP('l', ELEMENT_TYPE_LOGNAME);
- TYPE_MAP('m', ELEMENT_TYPE_METHOD);
- TYPE_MAP('p', ELEMENT_TYPE_LOCAL_PORT);
- TYPE_MAP('e', ELEMENT_TYPE_ENV_VAR);
- TYPE_MAP('q', ELEMENT_TYPE_QUERY);
- TYPE_MAP('r', ELEMENT_TYPE_REQUEST_LINE);
- TYPE_MAP('s', ELEMENT_TYPE_STATUS);
- TYPE_MAP('t', ELEMENT_TYPE_TIMESTAMP);
- TYPE_MAP('U', ELEMENT_TYPE_URL_PATH);
- TYPE_MAP('u', ELEMENT_TYPE_REMOTE_USER);
- TYPE_MAP('V', ELEMENT_TYPE_AUTHORITY);
- TYPE_MAP('v', ELEMENT_TYPE_HOSTCONF);
-#undef TYPE_MAP
- default:
- sprintf(errbuf, "failed to compile log format: unknown escape sequence: %%%c", pt[-1]);
- goto Error;
- }
- NEW_ELEMENT(type);
- LAST_ELEMENT()->original_response = log_original;
- continue;
- }
- }
- /* emit current char */
- if (logconf->elements.size == 0)
- NEW_ELEMENT(ELEMENT_TYPE_EMPTY);
- LAST_ELEMENT()->suffix.base[LAST_ELEMENT()->suffix.len++] = *pt++;
- }
-
- /* emit end-of-line */
- if (logconf->elements.size == 0)
- NEW_ELEMENT(ELEMENT_TYPE_EMPTY);
- LAST_ELEMENT()->suffix.base[LAST_ELEMENT()->suffix.len++] = '\n';
-
-#undef NEW_ELEMENT
-#undef LAST_ELEMENT
-
- if (escape == H2O_LOGCONF_ESCAPE_JSON) {
- if (!determine_magicquote_nodes(logconf, errbuf))
- goto Error;
- }
-
- return logconf;
-
-Error:
- h2o_logconf_dispose(logconf);
- return NULL;
-}
-
-void h2o_logconf_dispose(h2o_logconf_t *logconf)
-{
- size_t i;
-
- for (i = 0; i != logconf->elements.size; ++i) {
- free(logconf->elements.entries[i].suffix.base);
- switch (logconf->elements.entries[i].type) {
- case ELEMENT_TYPE_EXTENDED_VAR:
- case ELEMENT_TYPE_IN_HEADER_STRING:
- case ELEMENT_TYPE_OUT_HEADER_STRING:
- case ELEMENT_TYPE_TIMESTAMP_STRFTIME:
- free(logconf->elements.entries[i].data.name.base);
- break;
- default:
- break;
- }
- }
- free(logconf->elements.entries);
- free(logconf);
-}
-
-static inline char *append_safe_string(char *pos, const char *src, size_t len)
-{
- memcpy(pos, src, len);
- return pos + len;
-}
-
-static char *append_unsafe_string_apache(char *pos, const char *src, size_t len)
-{
- const char *src_end = src + len;
-
- for (; src != src_end; ++src) {
- if (' ' <= *src && *src < 0x7d && *src != '"') {
- *pos++ = *src;
- } else {
- *pos++ = '\\';
- *pos++ = 'x';
- *pos++ = ("0123456789abcdef")[(*src >> 4) & 0xf];
- *pos++ = ("0123456789abcdef")[*src & 0xf];
- }
- }
-
- return pos;
-}
-
-static char *append_unsafe_string_json(char *pos, const char *src, size_t len)
-{
- const char *src_end = src + len;
-
- for (; src != src_end; ++src) {
- if (' ' <= *src && *src < 0x7e) {
- if (*src == '"' || *src == '\\')
- *pos++ = '\\';
- *pos++ = *src;
- } else {
- *pos++ = '\\';
- *pos++ = 'u';
- *pos++ = '0';
- *pos++ = '0';
- *pos++ = ("0123456789abcdef")[(*src >> 4) & 0xf];
- *pos++ = ("0123456789abcdef")[*src & 0xf];
- }
- }
-
- return pos;
-}
-
-static char *append_addr(char *pos, socklen_t (*cb)(h2o_conn_t *conn, struct sockaddr *sa), h2o_conn_t *conn, h2o_iovec_t nullexpr)
-{
- struct sockaddr_storage ss;
- socklen_t sslen;
-
- if ((sslen = cb(conn, (void *)&ss)) == 0)
- goto Fail;
- size_t l = h2o_socket_getnumerichost((void *)&ss, sslen, pos);
- if (l == SIZE_MAX)
- goto Fail;
- pos += l;
- return pos;
-
-Fail:
- memcpy(pos, nullexpr.base, nullexpr.len);
- pos += nullexpr.len;
- return pos;
-}
-
-static char *append_port(char *pos, socklen_t (*cb)(h2o_conn_t *conn, struct sockaddr *sa), h2o_conn_t *conn, h2o_iovec_t nullexpr)
-{
- struct sockaddr_storage ss;
- socklen_t sslen;
-
- if ((sslen = cb(conn, (void *)&ss)) == 0)
- goto Fail;
- int32_t port = h2o_socket_getport((void *)&ss);
- if (port == -1)
- goto Fail;
- pos += sprintf(pos, "%" PRIu16, (uint16_t)port);
- return pos;
-
-Fail:
- memcpy(pos, nullexpr.base, nullexpr.len);
- pos += nullexpr.len;
- return pos;
-}
-
-#define APPEND_DURATION(pos, name) \
- do { \
- int64_t delta_usec; \
- if (!h2o_time_compute_##name(req, &delta_usec)) \
- goto EmitNull; \
- int32_t delta_sec = (int32_t)(delta_usec / (1000 * 1000)); \
- delta_usec -= ((int64_t)delta_sec * (1000 * 1000)); \
- RESERVE(sizeof(H2O_INT32_LONGEST_STR ".999999") - 1); \
- pos += sprintf(pos, "%" PRId32, delta_sec); \
- if (delta_usec != 0) { \
- int i; \
- *pos++ = '.'; \
- for (i = 5; i >= 0; --i) { \
- pos[i] = '0' + delta_usec % 10; \
- delta_usec /= 10; \
- } \
- pos += 6; \
- } \
- } while (0);
-
-static char *expand_line_buf(char *line, size_t *cur_size, size_t required, int should_realloc)
-{
- size_t new_size = *cur_size;
-
- /* determine the new size */
- do {
- new_size *= 2;
- } while (new_size < required);
-
- /* reallocate */
- if (!should_realloc) {
- char *newpt = h2o_mem_alloc(new_size);
- memcpy(newpt, line, *cur_size);
- line = newpt;
- } else {
- line = h2o_mem_realloc(line, new_size);
- }
- *cur_size = new_size;
-
- return line;
-}
-
-char *h2o_log_request(h2o_logconf_t *logconf, h2o_req_t *req, size_t *len, char *buf)
-{
- char *line = buf, *pos = line, *line_end = line + *len;
- h2o_iovec_t nullexpr;
- char *(*append_unsafe_string)(char *pos, const char *src, size_t len);
- size_t element_index, unsafe_factor;
- struct tm localt = {0};
- int should_realloc_on_expand = 0;
-
- switch (logconf->escape) {
- case H2O_LOGCONF_ESCAPE_APACHE:
- nullexpr = h2o_iovec_init(H2O_STRLIT("-"));
- append_unsafe_string = append_unsafe_string_apache;
- unsafe_factor = 4;
- break;
- case H2O_LOGCONF_ESCAPE_JSON:
- nullexpr = h2o_iovec_init(H2O_STRLIT("null"));
- append_unsafe_string = append_unsafe_string_json;
- unsafe_factor = 6;
- break;
- default:
- h2o_fatal("unexpected escape mode");
- break;
- }
-
- for (element_index = 0; element_index != logconf->elements.size; ++element_index) {
- struct log_element_t *element = logconf->elements.entries + element_index;
-
-/* reserve capacity + suffix.len */
-#define RESERVE(capacity) \
- do { \
- if ((capacity) + element->suffix.len > line_end - pos) { \
- size_t off = pos - line; \
- size_t size = line_end - line; \
- line = expand_line_buf(line, &size, off + (capacity) + element->suffix.len, should_realloc_on_expand); \
- pos = line + off; \
- line_end = line + size; \
- should_realloc_on_expand = 1; \
- } \
- } while (0)
-
- switch (element->type) {
- case ELEMENT_TYPE_EMPTY:
- RESERVE(0);
- break;
- case ELEMENT_TYPE_LOCAL_ADDR: /* %A */
- RESERVE(NI_MAXHOST);
- pos = append_addr(pos, req->conn->callbacks->get_sockname, req->conn, nullexpr);
- break;
- case ELEMENT_TYPE_BYTES_SENT: /* %b */
- RESERVE(sizeof(H2O_UINT64_LONGEST_STR) - 1);
- pos += sprintf(pos, "%" PRIu64, (uint64_t)req->bytes_sent);
- break;
- case ELEMENT_TYPE_PROTOCOL: /* %H */
- RESERVE(sizeof("HTTP/1.1"));
- pos += h2o_stringify_protocol_version(pos, req->version);
- break;
- case ELEMENT_TYPE_REMOTE_ADDR: /* %h */
- RESERVE(NI_MAXHOST);
- pos = append_addr(pos, req->conn->callbacks->get_peername, req->conn, nullexpr);
- break;
- case ELEMENT_TYPE_METHOD: /* %m */
- RESERVE(req->input.method.len * unsafe_factor);
- pos = append_unsafe_string(pos, req->input.method.base, req->input.method.len);
- break;
- case ELEMENT_TYPE_LOCAL_PORT: /* %p */
- RESERVE(sizeof(H2O_UINT16_LONGEST_STR) - 1);
- pos = append_port(pos, req->conn->callbacks->get_sockname, req->conn, nullexpr);
- break;
- case ELEMENT_TYPE_REMOTE_PORT: /* %{remote}p */
- RESERVE(sizeof(H2O_UINT16_LONGEST_STR) - 1);
- pos = append_port(pos, req->conn->callbacks->get_peername, req->conn, nullexpr);
- break;
- case ELEMENT_TYPE_ENV_VAR: /* %{..}e */ {
- h2o_iovec_t *env_var = h2o_req_getenv(req, element->data.name.base, element->data.name.len, 0);
- if (env_var == NULL)
- goto EmitNull;
- RESERVE(env_var->len * unsafe_factor);
- pos = append_safe_string(pos, env_var->base, env_var->len);
- } break;
- case ELEMENT_TYPE_QUERY: /* %q */
- if (req->input.query_at != SIZE_MAX) {
- size_t len = req->input.path.len - req->input.query_at;
- RESERVE(len * unsafe_factor);
- pos = append_unsafe_string(pos, req->input.path.base + req->input.query_at, len);
- }
- break;
- case ELEMENT_TYPE_REQUEST_LINE: /* %r */
- RESERVE((req->input.method.len + req->input.path.len) * unsafe_factor + sizeof(" HTTP/1.1"));
- pos = append_unsafe_string(pos, req->input.method.base, req->input.method.len);
- *pos++ = ' ';
- pos = append_unsafe_string(pos, req->input.path.base, req->input.path.len);
- *pos++ = ' ';
- pos += h2o_stringify_protocol_version(pos, req->version);
- break;
- case ELEMENT_TYPE_STATUS: /* %s */
- RESERVE(sizeof(H2O_INT32_LONGEST_STR) - 1);
- pos += sprintf(pos, "%" PRId32, (int32_t)(element->original_response ? req->res.original.status : req->res.status));
- break;
- case ELEMENT_TYPE_TIMESTAMP: /* %t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(H2O_TIMESTR_LOG_LEN + 2);
- *pos++ = '[';
- pos = append_safe_string(pos, req->processed_at.str->log, H2O_TIMESTR_LOG_LEN);
- *pos++ = ']';
- break;
- case ELEMENT_TYPE_TIMESTAMP_STRFTIME: /* %{...}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- {
- size_t bufsz, len;
- if (localt.tm_year == 0)
- localtime_r(&req->processed_at.at.tv_sec, &localt);
- for (bufsz = 128;; bufsz *= 2) {
- RESERVE(bufsz);
- if ((len = strftime(pos, bufsz, element->data.name.base, &localt)) != 0)
- break;
- }
- pos += len;
- }
- break;
- case ELEMENT_TYPE_TIMESTAMP_SEC_SINCE_EPOCH: /* %{sec}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(sizeof(H2O_UINT32_LONGEST_STR) - 1);
- pos += sprintf(pos, "%" PRIu32, (uint32_t)req->processed_at.at.tv_sec);
- break;
- case ELEMENT_TYPE_TIMESTAMP_MSEC_SINCE_EPOCH: /* %{msec}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(sizeof(H2O_UINT64_LONGEST_STR) - 1);
- pos += sprintf(pos, "%" PRIu64,
- (uint64_t)req->processed_at.at.tv_sec * 1000 + (uint64_t)req->processed_at.at.tv_usec / 1000);
- break;
- case ELEMENT_TYPE_TIMESTAMP_USEC_SINCE_EPOCH: /* %{usec}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(sizeof(H2O_UINT64_LONGEST_STR) - 1);
- pos +=
- sprintf(pos, "%" PRIu64, (uint64_t)req->processed_at.at.tv_sec * 1000000 + (uint64_t)req->processed_at.at.tv_usec);
- break;
- case ELEMENT_TYPE_TIMESTAMP_MSEC_FRAC: /* %{msec_frac}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(3);
- pos += sprintf(pos, "%03u", (unsigned)(req->processed_at.at.tv_usec / 1000));
- break;
- case ELEMENT_TYPE_TIMESTAMP_USEC_FRAC: /* %{usec_frac}t */
- if (h2o_timeval_is_null(&req->processed_at.at))
- goto EmitNull;
- RESERVE(6);
- pos += sprintf(pos, "%06u", (unsigned)req->processed_at.at.tv_usec);
- break;
- case ELEMENT_TYPE_URL_PATH: /* %U */ {
- size_t path_len = req->input.query_at == SIZE_MAX ? req->input.path.len : req->input.query_at;
- RESERVE(path_len * unsafe_factor);
- pos = append_unsafe_string(pos, req->input.path.base, path_len);
- } break;
- case ELEMENT_TYPE_REMOTE_USER: /* %u */ {
- h2o_iovec_t *remote_user = h2o_req_getenv(req, H2O_STRLIT("REMOTE_USER"), 0);
- if (remote_user == NULL)
- goto EmitNull;
- RESERVE(remote_user->len * unsafe_factor);
- pos = append_unsafe_string(pos, remote_user->base, remote_user->len);
- } break;
- case ELEMENT_TYPE_AUTHORITY: /* %V */
- RESERVE(req->input.authority.len * unsafe_factor);
- pos = append_unsafe_string(pos, req->input.authority.base, req->input.authority.len);
- break;
- case ELEMENT_TYPE_HOSTCONF: /* %v */
- RESERVE(req->hostconf->authority.hostport.len * unsafe_factor);
- pos = append_unsafe_string(pos, req->hostconf->authority.hostport.base, req->hostconf->authority.hostport.len);
- break;
-
-#define EMIT_HEADER(__headers, concat, findfunc, ...) \
- do { \
- h2o_headers_t *headers = (__headers); \
- ssize_t index = -1; \
- int found = 0; \
- while ((index = (findfunc)(headers, __VA_ARGS__, index)) != -1) { \
- if (found) { \
- RESERVE(2); \
- *pos++ = ','; \
- *pos++ = ' '; \
- } else { \
- found = 1; \
- } \
- const h2o_header_t *header = headers->entries + index; \
- RESERVE(header->value.len *unsafe_factor); \
- pos = append_unsafe_string(pos, header->value.base, header->value.len); \
- if (!concat) \
- break; \
- } \
- if (!found) \
- goto EmitNull; \
- } while (0)
-
- case ELEMENT_TYPE_IN_HEADER_TOKEN:
- EMIT_HEADER(&req->headers, 0, h2o_find_header, element->data.header_token);
- break;
- case ELEMENT_TYPE_IN_HEADER_STRING:
- EMIT_HEADER(&req->headers, 0, h2o_find_header_by_str, element->data.name.base, element->data.name.len);
- break;
- case ELEMENT_TYPE_OUT_HEADER_TOKEN:
- EMIT_HEADER(element->original_response ? &req->res.original.headers : &req->res.headers, 0, h2o_find_header,
- element->data.header_token);
- break;
- case ELEMENT_TYPE_OUT_HEADER_STRING:
- EMIT_HEADER(element->original_response ? &req->res.original.headers : &req->res.headers, 0, h2o_find_header_by_str,
- element->data.name.base, element->data.name.len);
- break;
- case ELEMENT_TYPE_OUT_HEADER_TOKEN_CONCATENATED:
- EMIT_HEADER(element->original_response ? &req->res.original.headers : &req->res.headers, 1, h2o_find_header,
- element->data.header_token);
- break;
-
-#undef EMIT_HEADER
-
- case ELEMENT_TYPE_CONNECTION_ID:
- RESERVE(sizeof(H2O_UINT64_LONGEST_STR) - 1);
- pos += sprintf(pos, "%" PRIu64, req->conn->id);
- break;
-
- case ELEMENT_TYPE_CONNECT_TIME:
- APPEND_DURATION(pos, connect_time);
- break;
-
- case ELEMENT_TYPE_REQUEST_HEADER_TIME:
- APPEND_DURATION(pos, header_time);
- break;
-
- case ELEMENT_TYPE_REQUEST_BODY_TIME:
- APPEND_DURATION(pos, body_time);
- break;
-
- case ELEMENT_TYPE_REQUEST_TOTAL_TIME:
- APPEND_DURATION(pos, request_total_time);
- break;
-
- case ELEMENT_TYPE_PROCESS_TIME:
- APPEND_DURATION(pos, process_time);
- break;
-
- case ELEMENT_TYPE_RESPONSE_TIME:
- APPEND_DURATION(pos, response_time);
- break;
-
- case ELEMENT_TYPE_DURATION:
- APPEND_DURATION(pos, duration);
- break;
-
- case ELEMENT_TYPE_ERROR: {
- size_t i;
- for (i = 0; i != req->error_logs.size; ++i) {
- h2o_req_error_log_t *log = req->error_logs.entries + i;
- size_t module_len = strlen(log->module);
- RESERVE(sizeof("[] ") - 1 + module_len + log->msg.len * unsafe_factor);
- *pos++ = '[';
- pos = append_safe_string(pos, log->module, module_len);
- *pos++ = ']';
- *pos++ = ' ';
- pos = append_unsafe_string(pos, log->msg.base, log->msg.len);
- }
- } break;
-
- case ELEMENT_TYPE_PROTOCOL_SPECIFIC: {
- h2o_iovec_t (*cb)(h2o_req_t *) = req->conn->callbacks->log_.callbacks[element->data.protocol_specific_callback_index];
- if (cb != NULL) {
- h2o_iovec_t s = cb(req);
- if (s.base == NULL)
- goto EmitNull;
- RESERVE(s.len);
- pos = append_safe_string(pos, s.base, s.len);
- } else {
- goto EmitNull;
- }
- } break;
-
- case ELEMENT_TYPE_LOGNAME: /* %l */
- case ELEMENT_TYPE_EXTENDED_VAR: /* %{...}x */
- EmitNull:
- RESERVE(nullexpr.len);
- /* special case that trims surrounding quotes */
- if (element->magically_quoted_json) {
- --pos;
- pos = append_safe_string(pos, nullexpr.base, nullexpr.len);
- pos = append_safe_string(pos, element->suffix.base + 1, element->suffix.len - 1);
- continue;
- }
- pos = append_safe_string(pos, nullexpr.base, nullexpr.len);
- break;
-
- default:
- assert(!"unknown type");
- break;
- }
-
-#undef RESERVE
-
- pos = append_safe_string(pos, element->suffix.base, element->suffix.len);
- }
-
- *len = pos - line;
- return line;
-}
diff --git a/web/server/h2o/libh2o/lib/core/proxy.c b/web/server/h2o/libh2o/lib/core/proxy.c
deleted file mode 100644
index edb4baf9d..000000000
--- a/web/server/h2o/libh2o/lib/core/proxy.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * Copyright (c) 2014,2015 DeNA Co., Ltd., Kazuho Oku, Masahiro Nagano
- *
- * 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 <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include "picohttpparser.h"
-#include "h2o.h"
-#include "h2o/http1.h"
-#include "h2o/http1client.h"
-#include "h2o/tunnel.h"
-
-struct rp_generator_t {
- h2o_generator_t super;
- h2o_req_t *src_req;
- h2o_http1client_t *client;
- struct {
- h2o_iovec_t bufs[2]; /* first buf is the request line and headers, the second is the POST content */
- int is_head;
- } up_req;
- h2o_buffer_t *last_content_before_send;
- h2o_doublebuffer_t sending;
- int is_websocket_handshake;
- int had_body_error; /* set if an error happened while fetching the body so that we can propagate the error */
-};
-
-struct rp_ws_upgrade_info_t {
- h2o_context_t *ctx;
- h2o_timeout_t *timeout;
- h2o_socket_t *upstream_sock;
-};
-
-static h2o_http1client_ctx_t *get_client_ctx(h2o_req_t *req)
-{
- h2o_req_overrides_t *overrides = req->overrides;
- if (overrides != NULL && overrides->client_ctx != NULL)
- return overrides->client_ctx;
- return &req->conn->ctx->proxy.client_ctx;
-}
-
-static h2o_iovec_t rewrite_location(h2o_mem_pool_t *pool, const char *location, size_t location_len, h2o_url_t *match,
- const h2o_url_scheme_t *req_scheme, h2o_iovec_t req_authority, h2o_iovec_t req_basepath)
-{
- h2o_url_t loc_parsed;
-
- if (h2o_url_parse(location, location_len, &loc_parsed) != 0)
- goto NoRewrite;
- if (loc_parsed.scheme != &H2O_URL_SCHEME_HTTP)
- goto NoRewrite;
- if (!h2o_url_hosts_are_equal(&loc_parsed, match))
- goto NoRewrite;
- if (h2o_url_get_port(&loc_parsed) != h2o_url_get_port(match))
- goto NoRewrite;
- if (loc_parsed.path.len < match->path.len)
- goto NoRewrite;
- if (memcmp(loc_parsed.path.base, match->path.base, match->path.len) != 0)
- goto NoRewrite;
-
- return h2o_concat(pool, req_scheme->name, h2o_iovec_init(H2O_STRLIT("://")), req_authority, req_basepath,
- h2o_iovec_init(loc_parsed.path.base + match->path.len, loc_parsed.path.len - match->path.len));
-
-NoRewrite:
- return (h2o_iovec_t){NULL};
-}
-
-static h2o_iovec_t build_request_merge_headers(h2o_mem_pool_t *pool, h2o_iovec_t merged, h2o_iovec_t added, int seperator)
-{
- if (added.len == 0)
- return merged;
- if (merged.len == 0)
- return added;
-
- size_t newlen = merged.len + 2 + added.len;
- char *buf = h2o_mem_alloc_pool(pool, newlen);
- memcpy(buf, merged.base, merged.len);
- buf[merged.len] = seperator;
- buf[merged.len + 1] = ' ';
- memcpy(buf + merged.len + 2, added.base, added.len);
- merged.base = buf;
- merged.len = newlen;
- return merged;
-}
-
-/*
- * A request without neither Content-Length or Transfer-Encoding header implies a zero-length request body (see 6th rule of RFC 7230
- * 3.3.3).
- * OTOH, section 3.3.3 states:
- *
- * A user agent SHOULD send a Content-Length in a request message when
- * no Transfer-Encoding is sent and the request method defines a meaning
- * for an enclosed payload body. For example, a Content-Length header
- * field is normally sent in a POST request even when the value is 0
- * (indicating an empty payload body). A user agent SHOULD NOT send a
- * Content-Length header field when the request message does not contain
- * a payload body and the method semantics do not anticipate such a
- * body.
- *
- * PUT and POST define a meaning for the payload body, let's emit a
- * Content-Length header if it doesn't exist already, since the server
- * might send a '411 Length Required' response.
- *
- * see also: ML thread starting at https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0580.html
- */
-static int req_requires_content_length(h2o_req_t *req)
-{
- int is_put_or_post =
- (req->method.len >= 1 && req->method.base[0] == 'P' && (h2o_memis(req->method.base, req->method.len, H2O_STRLIT("POST")) ||
- h2o_memis(req->method.base, req->method.len, H2O_STRLIT("PUT"))));
-
- return is_put_or_post && h2o_find_header(&req->res.headers, H2O_TOKEN_TRANSFER_ENCODING, -1) == -1;
-}
-
-static h2o_iovec_t build_request(h2o_req_t *req, int keepalive, int is_websocket_handshake, int use_proxy_protocol)
-{
- h2o_iovec_t buf;
- size_t offset = 0, remote_addr_len = SIZE_MAX;
- char remote_addr[NI_MAXHOST];
- struct sockaddr_storage ss;
- socklen_t sslen;
- h2o_iovec_t cookie_buf = {NULL}, xff_buf = {NULL}, via_buf = {NULL};
- int preserve_x_forwarded_proto = req->conn->ctx->globalconf->proxy.preserve_x_forwarded_proto;
- int emit_x_forwarded_headers = req->conn->ctx->globalconf->proxy.emit_x_forwarded_headers;
- int emit_via_header = req->conn->ctx->globalconf->proxy.emit_via_header;
-
- /* for x-f-f */
- if ((sslen = req->conn->callbacks->get_peername(req->conn, (void *)&ss)) != 0)
- remote_addr_len = h2o_socket_getnumerichost((void *)&ss, sslen, remote_addr);
-
- /* build response */
- buf.len = req->method.len + req->path.len + req->authority.len + 512;
- if (use_proxy_protocol)
- buf.len += H2O_PROXY_HEADER_MAX_LENGTH;
- buf.base = h2o_mem_alloc_pool(&req->pool, buf.len);
-
-#define RESERVE(sz) \
- do { \
- size_t required = offset + sz + 4 /* for "\r\n\r\n" */; \
- if (required > buf.len) { \
- do { \
- buf.len *= 2; \
- } while (required > buf.len); \
- char *newp = h2o_mem_alloc_pool(&req->pool, buf.len); \
- memcpy(newp, buf.base, offset); \
- buf.base = newp; \
- } \
- } while (0)
-#define APPEND(s, l) \
- do { \
- memcpy(buf.base + offset, (s), (l)); \
- offset += (l); \
- } while (0)
-#define APPEND_STRLIT(lit) APPEND((lit), sizeof(lit) - 1)
-#define FLATTEN_PREFIXED_VALUE(prefix, value, add_size) \
- do { \
- RESERVE(sizeof(prefix) - 1 + value.len + 2 + add_size); \
- APPEND_STRLIT(prefix); \
- if (value.len != 0) { \
- APPEND(value.base, value.len); \
- if (add_size != 0) { \
- buf.base[offset++] = ','; \
- buf.base[offset++] = ' '; \
- } \
- } \
- } while (0)
-
- if (use_proxy_protocol)
- offset += h2o_stringify_proxy_header(req->conn, buf.base + offset);
-
- APPEND(req->method.base, req->method.len);
- buf.base[offset++] = ' ';
- APPEND(req->path.base, req->path.len);
- APPEND_STRLIT(" HTTP/1.1\r\nconnection: ");
- if (is_websocket_handshake) {
- APPEND_STRLIT("upgrade\r\nupgrade: websocket\r\nhost: ");
- } else if (keepalive) {
- APPEND_STRLIT("keep-alive\r\nhost: ");
- } else {
- APPEND_STRLIT("close\r\nhost: ");
- }
- APPEND(req->authority.base, req->authority.len);
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- assert(offset <= buf.len);
- if (req->entity.base != NULL || req_requires_content_length(req)) {
- RESERVE(sizeof("content-length: " H2O_UINT64_LONGEST_STR) - 1);
- offset += sprintf(buf.base + offset, "content-length: %zu\r\n", req->entity.len);
- }
-
- /* rewrite headers if necessary */
- h2o_headers_t req_headers = req->headers;
- if (req->overrides != NULL && req->overrides->headers_cmds != NULL) {
- req_headers.entries = NULL;
- req_headers.size = 0;
- req_headers.capacity = 0;
- h2o_headers_command_t *cmd;
- h2o_vector_reserve(&req->pool, &req_headers, req->headers.capacity);
- memcpy(req_headers.entries, req->headers.entries, sizeof(req->headers.entries[0]) * req->headers.size);
- req_headers.size = req->headers.size;
- for (cmd = req->overrides->headers_cmds; cmd->cmd != H2O_HEADERS_CMD_NULL; ++cmd)
- h2o_rewrite_headers(&req->pool, &req_headers, cmd);
- }
-
- {
- const h2o_header_t *h, *h_end;
- for (h = req_headers.entries, h_end = h + req_headers.size; h != h_end; ++h) {
- if (h2o_iovec_is_token(h->name)) {
- const h2o_token_t *token = (void *)h->name;
- if (token->proxy_should_drop_for_req) {
- continue;
- } else if (token == H2O_TOKEN_COOKIE) {
- /* merge the cookie headers; see HTTP/2 8.1.2.5 and HTTP/1 (RFC6265 5.4) */
- /* FIXME current algorithm is O(n^2) against the number of cookie headers */
- cookie_buf = build_request_merge_headers(&req->pool, cookie_buf, h->value, ';');
- continue;
- } else if (token == H2O_TOKEN_VIA) {
- if (!emit_via_header) {
- goto AddHeader;
- }
- via_buf = build_request_merge_headers(&req->pool, via_buf, h->value, ',');
- continue;
- } else if (token == H2O_TOKEN_X_FORWARDED_FOR) {
- if (!emit_x_forwarded_headers) {
- goto AddHeader;
- }
- xff_buf = build_request_merge_headers(&req->pool, xff_buf, h->value, ',');
- continue;
- }
- }
- if (!preserve_x_forwarded_proto && h2o_lcstris(h->name->base, h->name->len, H2O_STRLIT("x-forwarded-proto")))
- continue;
- AddHeader:
- RESERVE(h->name->len + h->value.len + 2);
- APPEND(h->orig_name ? h->orig_name : h->name->base, h->name->len);
- buf.base[offset++] = ':';
- buf.base[offset++] = ' ';
- APPEND(h->value.base, h->value.len);
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- }
- }
- if (cookie_buf.len != 0) {
- FLATTEN_PREFIXED_VALUE("cookie: ", cookie_buf, 0);
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- }
- if (emit_x_forwarded_headers) {
- if (!preserve_x_forwarded_proto) {
- FLATTEN_PREFIXED_VALUE("x-forwarded-proto: ", req->input.scheme->name, 0);
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- }
- if (remote_addr_len != SIZE_MAX) {
- FLATTEN_PREFIXED_VALUE("x-forwarded-for: ", xff_buf, remote_addr_len);
- APPEND(remote_addr, remote_addr_len);
- } else {
- FLATTEN_PREFIXED_VALUE("x-forwarded-for: ", xff_buf, 0);
- }
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- }
- if (emit_via_header) {
- FLATTEN_PREFIXED_VALUE("via: ", via_buf, sizeof("1.1 ") - 1 + req->input.authority.len);
- if (req->version < 0x200) {
- buf.base[offset++] = '1';
- buf.base[offset++] = '.';
- buf.base[offset++] = '0' + (0x100 <= req->version && req->version <= 0x109 ? req->version - 0x100 : 0);
- } else {
- buf.base[offset++] = '2';
- }
- buf.base[offset++] = ' ';
- APPEND(req->input.authority.base, req->input.authority.len);
- buf.base[offset++] = '\r';
- buf.base[offset++] = '\n';
- }
- APPEND_STRLIT("\r\n");
-
-#undef RESERVE
-#undef APPEND
-#undef APPEND_STRLIT
-#undef FLATTEN_PREFIXED_VALUE
-
- /* set the length */
- assert(offset <= buf.len);
- buf.len = offset;
-
- return buf;
-}
-
-static void do_close(h2o_generator_t *generator, h2o_req_t *req)
-{
- struct rp_generator_t *self = (void *)generator;
-
- if (self->client != NULL) {
- h2o_http1client_cancel(self->client);
- self->client = NULL;
- }
-}
-
-static void do_send(struct rp_generator_t *self)
-{
- h2o_iovec_t vecs[1];
- size_t veccnt;
- h2o_send_state_t ststate;
-
- assert(self->sending.bytes_inflight == 0);
-
- vecs[0] = h2o_doublebuffer_prepare(&self->sending,
- self->client != NULL ? &self->client->sock->input : &self->last_content_before_send,
- self->src_req->preferred_chunk_size);
-
- if (self->client == NULL && vecs[0].len == self->sending.buf->size && self->last_content_before_send->size == 0) {
- veccnt = vecs[0].len != 0 ? 1 : 0;
- ststate = H2O_SEND_STATE_FINAL;
- } else {
- if (vecs[0].len == 0)
- return;
- veccnt = 1;
- ststate = H2O_SEND_STATE_IN_PROGRESS;
- }
-
- if (self->had_body_error)
- ststate = H2O_SEND_STATE_ERROR;
-
- h2o_send(self->src_req, vecs, veccnt, ststate);
-}
-
-static void do_proceed(h2o_generator_t *generator, h2o_req_t *req)
-{
- struct rp_generator_t *self = (void *)generator;
-
- h2o_doublebuffer_consume(&self->sending);
- do_send(self);
-}
-
-static void on_websocket_upgrade_complete(void *_info, h2o_socket_t *sock, size_t reqsize)
-{
- struct rp_ws_upgrade_info_t *info = _info;
-
- if (sock != NULL) {
- h2o_buffer_consume(&sock->input, reqsize);//It is detached from conn. Let's trash unused data.
- h2o_tunnel_establish(info->ctx, sock, info->upstream_sock, info->timeout);
- } else {
- h2o_socket_close(info->upstream_sock);
- }
- free(info);
-}
-
-static inline void on_websocket_upgrade(struct rp_generator_t *self, h2o_timeout_t *timeout, int rlen)
-{
- h2o_req_t *req = self->src_req;
- h2o_socket_t *sock = h2o_http1client_steal_socket(self->client);
- h2o_buffer_consume(&sock->input, rlen);//trash data after stealing sock.
- struct rp_ws_upgrade_info_t *info = h2o_mem_alloc(sizeof(*info));
- info->upstream_sock = sock;
- info->timeout = timeout;
- info->ctx = req->conn->ctx;
- h2o_http1_upgrade(req, NULL, 0, on_websocket_upgrade_complete, info);
-}
-
-static int on_body(h2o_http1client_t *client, const char *errstr)
-{
- struct rp_generator_t *self = client->data;
-
- if (errstr != NULL) {
- /* detach the content */
- self->last_content_before_send = self->client->sock->input;
- h2o_buffer_init(&self->client->sock->input, &h2o_socket_buffer_prototype);
- self->client = NULL;
- if (errstr != h2o_http1client_error_is_eos) {
- h2o_req_log_error(self->src_req, "lib/core/proxy.c", "%s", errstr);
- self->had_body_error = 1;
- }
- }
- if (self->sending.bytes_inflight == 0)
- do_send(self);
-
- return 0;
-}
-
-static char compress_hint_to_enum(const char *val, size_t len)
-{
- if (h2o_lcstris(val, len, H2O_STRLIT("on"))) {
- return H2O_COMPRESS_HINT_ENABLE;
- }
- if (h2o_lcstris(val, len, H2O_STRLIT("off"))) {
- return H2O_COMPRESS_HINT_DISABLE;
- }
- return H2O_COMPRESS_HINT_AUTO;
-}
-
-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, int rlen)
-{
- struct rp_generator_t *self = client->data;
- h2o_req_t *req = self->src_req;
- size_t i;
-
- if (errstr != NULL && errstr != h2o_http1client_error_is_eos) {
- self->client = NULL;
- h2o_req_log_error(req, "lib/core/proxy.c", "%s", errstr);
- h2o_send_error_502(req, "Gateway Error", errstr, 0);
- return NULL;
- }
-
- /* copy the response (note: all the headers must be copied; http1client discards the input once we return from this callback) */
- req->res.status = status;
- req->res.reason = h2o_strdup(&req->pool, msg.base, msg.len).base;
- for (i = 0; i != num_headers; ++i) {
- if (h2o_iovec_is_token(headers[i].name)) {
- const h2o_token_t *token = H2O_STRUCT_FROM_MEMBER(h2o_token_t, buf, headers[i].name);
- h2o_iovec_t value;
- if (token->proxy_should_drop_for_res) {
- goto Skip;
- }
- if (token == H2O_TOKEN_CONTENT_LENGTH) {
- if (req->res.content_length != SIZE_MAX ||
- (req->res.content_length = h2o_strtosize(headers[i].value.base, headers[i].value.len)) == SIZE_MAX) {
- self->client = NULL;
- h2o_req_log_error(req, "lib/core/proxy.c", "%s", "invalid response from upstream (malformed content-length)");
- h2o_send_error_502(req, "Gateway Error", "invalid response from upstream", 0);
- return NULL;
- }
- goto Skip;
- } else if (token == H2O_TOKEN_LOCATION) {
- if (req->res_is_delegated && (300 <= status && status <= 399) && status != 304) {
- self->client = NULL;
- h2o_iovec_t method = h2o_get_redirect_method(req->method, status);
- h2o_send_redirect_internal(req, method, headers[i].value.base, headers[i].value.len, 1);
- return NULL;
- }
- if (req->overrides != NULL && req->overrides->location_rewrite.match != NULL) {
- value = rewrite_location(&req->pool, headers[i].value.base, headers[i].value.len,
- req->overrides->location_rewrite.match, req->input.scheme, req->input.authority,
- req->overrides->location_rewrite.path_prefix);
- if (value.base != NULL)
- goto AddHeader;
- }
- goto AddHeaderDuped;
- } else if (token == H2O_TOKEN_LINK) {
- h2o_iovec_t new_value;
- new_value = h2o_push_path_in_link_header(req, headers[i].value.base, headers[i].value.len);
- if (!new_value.len)
- goto Skip;
- headers[i].value.base = new_value.base;
- headers[i].value.len = new_value.len;
- } else if (token == H2O_TOKEN_SERVER) {
- if (!req->conn->ctx->globalconf->proxy.preserve_server_header)
- goto Skip;
- } else if (token == H2O_TOKEN_X_COMPRESS_HINT) {
- req->compress_hint = compress_hint_to_enum(headers[i].value.base, headers[i].value.len);
- goto Skip;
- }
- /* default behaviour, transfer the header downstream */
- AddHeaderDuped:
- value = h2o_strdup(&req->pool, headers[i].value.base, headers[i].value.len);
- AddHeader:
- h2o_add_header(&req->pool, &req->res.headers, token, headers[i].orig_name, value.base, value.len);
- Skip:;
- } else {
- h2o_iovec_t name = h2o_strdup(&req->pool, headers[i].name->base, headers[i].name->len);
- h2o_iovec_t value = h2o_strdup(&req->pool, headers[i].value.base, headers[i].value.len);
- h2o_add_header_by_str(&req->pool, &req->res.headers, name.base, name.len, 0, headers[i].orig_name, value.base,
- value.len);
- }
- }
-
- if (self->is_websocket_handshake && req->res.status == 101) {
- h2o_http1client_ctx_t *client_ctx = get_client_ctx(req);
- assert(client_ctx->websocket_timeout != NULL);
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_UPGRADE, NULL, H2O_STRLIT("websocket"));
- on_websocket_upgrade(self, client_ctx->websocket_timeout, rlen);
- self->client = NULL;
- return NULL;
- }
- /* declare the start of the response */
- h2o_start_response(req, &self->super);
-
- if (errstr == h2o_http1client_error_is_eos) {
- self->client = NULL;
- h2o_send(req, NULL, 0, H2O_SEND_STATE_FINAL);
- return NULL;
- }
-
- return on_body;
-}
-
-static int on_1xx(h2o_http1client_t *client, int minor_version, int status, h2o_iovec_t msg, h2o_header_t *headers,
- size_t num_headers)
-{
- struct rp_generator_t *self = client->data;
- size_t i;
-
- for (i = 0; i != num_headers; ++i) {
- if (headers[i].name == &H2O_TOKEN_LINK->buf)
- h2o_push_path_in_link_header(self->src_req, headers[i].value.base, headers[i].value.len);
- }
-
- return 0;
-}
-
-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)
-{
- struct rp_generator_t *self = client->data;
-
- if (errstr != NULL) {
- self->client = NULL;
- h2o_req_log_error(self->src_req, "lib/core/proxy.c", "%s", errstr);
- h2o_send_error_502(self->src_req, "Gateway Error", errstr, 0);
- return NULL;
- }
-
- *reqbufs = self->up_req.bufs;
- *reqbufcnt = self->up_req.bufs[1].base != NULL ? 2 : 1;
- *method_is_head = self->up_req.is_head;
- self->client->informational_cb = on_1xx;
- return on_head;
-}
-
-static void on_generator_dispose(void *_self)
-{
- struct rp_generator_t *self = _self;
-
- if (self->client != NULL) {
- h2o_http1client_cancel(self->client);
- self->client = NULL;
- }
- h2o_buffer_dispose(&self->last_content_before_send);
- h2o_doublebuffer_dispose(&self->sending);
-}
-
-static struct rp_generator_t *proxy_send_prepare(h2o_req_t *req, int keepalive, int use_proxy_protocol)
-{
- struct rp_generator_t *self = h2o_mem_alloc_shared(&req->pool, sizeof(*self), on_generator_dispose);
- h2o_http1client_ctx_t *client_ctx = get_client_ctx(req);
-
- self->super.proceed = do_proceed;
- self->super.stop = do_close;
- self->src_req = req;
- if (client_ctx->websocket_timeout != NULL && h2o_lcstris(req->upgrade.base, req->upgrade.len, H2O_STRLIT("websocket"))) {
- self->is_websocket_handshake = 1;
- } else {
- self->is_websocket_handshake = 0;
- }
- self->had_body_error = 0;
- self->up_req.bufs[0] = build_request(req, keepalive, self->is_websocket_handshake, use_proxy_protocol);
- self->up_req.bufs[1] = req->entity;
- self->up_req.is_head = h2o_memis(req->method.base, req->method.len, H2O_STRLIT("HEAD"));
- h2o_buffer_init(&self->last_content_before_send, &h2o_socket_buffer_prototype);
- h2o_doublebuffer_init(&self->sending, &h2o_socket_buffer_prototype);
-
- return self;
-}
-
-void h2o__proxy_process_request(h2o_req_t *req)
-{
- h2o_req_overrides_t *overrides = req->overrides;
- h2o_http1client_ctx_t *client_ctx = get_client_ctx(req);
- struct rp_generator_t *self;
-
- if (overrides != NULL) {
- if (overrides->socketpool != NULL) {
- if (overrides->use_proxy_protocol)
- assert(!"proxy protocol cannot be used for a persistent upstream connection");
- self = proxy_send_prepare(req, 1, 0);
- h2o_http1client_connect_with_pool(&self->client, self, client_ctx, overrides->socketpool, on_connect);
- return;
- } else if (overrides->hostport.host.base != NULL) {
- self = proxy_send_prepare(req, 0, overrides->use_proxy_protocol);
- h2o_http1client_connect(&self->client, self, client_ctx, req->overrides->hostport.host, req->overrides->hostport.port,
- 0, on_connect);
- return;
- }
- }
- { /* default logic */
- h2o_iovec_t host;
- uint16_t port;
- if (h2o_url_parse_hostport(req->authority.base, req->authority.len, &host, &port) == NULL) {
- h2o_req_log_error(req, "lib/core/proxy.c", "invalid URL supplied for internal redirection:%s://%.*s%.*s",
- req->scheme->name.base, (int)req->authority.len, req->authority.base, (int)req->path.len,
- req->path.base);
- h2o_send_error_502(req, "Gateway Error", "internal error", 0);
- return;
- }
- if (port == 65535)
- port = req->scheme->default_port;
- self = proxy_send_prepare(req, 0, overrides != NULL && overrides->use_proxy_protocol);
- h2o_http1client_connect(&self->client, self, client_ctx, host, port, req->scheme == &H2O_URL_SCHEME_HTTPS, on_connect);
- return;
- }
-}
diff --git a/web/server/h2o/libh2o/lib/core/request.c b/web/server/h2o/libh2o/lib/core/request.c
deleted file mode 100644
index 96aabb22d..000000000
--- a/web/server/h2o/libh2o/lib/core/request.c
+++ /dev/null
@@ -1,696 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Tatsuhiro Tsujikawa
- *
- * 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 <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/uio.h>
-#include "h2o.h"
-
-#ifndef IOV_MAX
-#define IOV_MAX UIO_MAXIOV
-#endif
-
-#define INITIAL_INBUFSZ 8192
-
-struct st_deferred_request_action_t {
- h2o_timeout_entry_t timeout;
- h2o_req_t *req;
-};
-
-struct st_delegate_request_deferred_t {
- struct st_deferred_request_action_t super;
- h2o_handler_t *current_handler;
-};
-
-struct st_reprocess_request_deferred_t {
- struct st_deferred_request_action_t super;
- h2o_iovec_t method;
- const h2o_url_scheme_t *scheme;
- h2o_iovec_t authority;
- h2o_iovec_t path;
- h2o_req_overrides_t *overrides;
- int is_delegated;
-};
-
-struct st_send_error_deferred_t {
- h2o_req_t *req;
- int status;
- const char *reason;
- const char *body;
- int flags;
- h2o_timeout_entry_t _timeout;
-};
-
-static void on_deferred_action_dispose(void *_action)
-{
- struct st_deferred_request_action_t *action = _action;
- if (h2o_timeout_is_linked(&action->timeout))
- h2o_timeout_unlink(&action->timeout);
-}
-
-static struct st_deferred_request_action_t *create_deferred_action(h2o_req_t *req, size_t sz, h2o_timeout_cb cb)
-{
- struct st_deferred_request_action_t *action = h2o_mem_alloc_shared(&req->pool, sz, on_deferred_action_dispose);
- *action = (struct st_deferred_request_action_t){{0, cb}, req};
- h2o_timeout_link(req->conn->ctx->loop, &req->conn->ctx->zero_timeout, &action->timeout);
- return action;
-}
-
-static h2o_hostconf_t *find_hostconf(h2o_hostconf_t **hostconfs, h2o_iovec_t authority, uint16_t default_port)
-{
- h2o_iovec_t hostname;
- uint16_t port;
- char *hostname_lc;
-
- /* safe-guard for alloca */
- if (authority.len >= 65536)
- return NULL;
-
- /* extract the specified hostname and port */
- if (h2o_url_parse_hostport(authority.base, authority.len, &hostname, &port) == NULL)
- return NULL;
- if (port == 65535)
- port = default_port;
-
- /* convert supplied hostname to lower-case */
- hostname_lc = alloca(hostname.len);
- memcpy(hostname_lc, hostname.base, hostname.len);
- h2o_strtolower(hostname_lc, hostname.len);
-
- do {
- h2o_hostconf_t *hostconf = *hostconfs;
- if (hostconf->authority.port == port || (hostconf->authority.port == 65535 && port == default_port)) {
- if (hostconf->authority.host.base[0] == '*') {
- /* matching against "*.foo.bar" */
- size_t cmplen = hostconf->authority.host.len - 1;
- if (cmplen < hostname.len &&
- memcmp(hostconf->authority.host.base + 1, hostname_lc + hostname.len - cmplen, cmplen) == 0)
- return hostconf;
- } else {
- /* exact match */
- if (h2o_memis(hostconf->authority.host.base, hostconf->authority.host.len, hostname_lc, hostname.len))
- return hostconf;
- }
- }
- } while (*++hostconfs != NULL);
-
- return NULL;
-}
-
-static h2o_hostconf_t *setup_before_processing(h2o_req_t *req)
-{
- h2o_context_t *ctx = req->conn->ctx;
- h2o_hostconf_t *hostconf;
-
- h2o_get_timestamp(ctx, &req->pool, &req->processed_at);
-
- /* find the host context */
- if (req->input.authority.base != NULL) {
- if (req->conn->hosts[1] == NULL ||
- (hostconf = find_hostconf(req->conn->hosts, req->input.authority, req->input.scheme->default_port)) == NULL)
- hostconf = *req->conn->hosts;
- } else {
- /* set the authority name to the default one */
- hostconf = *req->conn->hosts;
- req->input.authority = hostconf->authority.hostport;
- }
-
- req->scheme = req->input.scheme;
- req->method = req->input.method;
- req->authority = req->input.authority;
- req->path = req->input.path;
- req->path_normalized =
- h2o_url_normalize_path(&req->pool, req->input.path.base, req->input.path.len, &req->query_at, &req->norm_indexes);
- req->input.query_at = req->query_at; /* we can do this since input.path == path */
-
- return hostconf;
-}
-
-static void call_handlers(h2o_req_t *req, h2o_handler_t **handler)
-{
- h2o_handler_t **end = req->pathconf->handlers.entries + req->pathconf->handlers.size;
-
- for (; handler != end; ++handler)
- if ((*handler)->on_req(*handler, req) == 0)
- return;
-
- h2o_send_error_404(req, "File Not Found", "not found", 0);
-}
-
-static void process_hosted_request(h2o_req_t *req, h2o_hostconf_t *hostconf)
-{
- h2o_pathconf_t *selected_pathconf = &hostconf->fallback_path;
- size_t i;
-
- /* setup pathconf, or redirect to "path/" */
- for (i = 0; i != hostconf->paths.size; ++i) {
- h2o_pathconf_t *candidate = hostconf->paths.entries + i;
- if (req->path_normalized.len >= candidate->path.len &&
- memcmp(req->path_normalized.base, candidate->path.base, candidate->path.len) == 0 &&
- (candidate->path.base[candidate->path.len - 1] == '/' || req->path_normalized.len == candidate->path.len ||
- req->path_normalized.base[candidate->path.len] == '/')) {
- selected_pathconf = candidate;
- break;
- }
- }
- h2o_req_bind_conf(req, hostconf, selected_pathconf);
-
- call_handlers(req, req->pathconf->handlers.entries);
-}
-
-static void deferred_proceed_cb(h2o_timeout_entry_t *entry)
-{
- h2o_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_req_t, _timeout_entry, entry);
- h2o_proceed_response(req);
-}
-
-static void close_generator_and_filters(h2o_req_t *req)
-{
- /* close the generator if it is still open */
- if (req->_generator != NULL) {
- /* close generator */
- if (req->_generator->stop != NULL)
- req->_generator->stop(req->_generator, req);
- req->_generator = NULL;
- }
- /* close the ostreams still open */
- while (req->_ostr_top->next != NULL) {
- if (req->_ostr_top->stop != NULL)
- req->_ostr_top->stop(req->_ostr_top, req);
- req->_ostr_top = req->_ostr_top->next;
- }
-}
-
-static void reset_response(h2o_req_t *req)
-{
- req->res = (h2o_res_t){0, NULL, SIZE_MAX};
- req->res.reason = "OK";
- req->_next_filter_index = 0;
- req->bytes_sent = 0;
-}
-
-static void retain_original_response(h2o_req_t *req)
-{
- if (req->res.original.status != 0)
- return;
-
- req->res.original.status = req->res.status;
- h2o_vector_reserve(&req->pool, &req->res.original.headers, req->res.headers.size);
- h2o_memcpy(req->res.original.headers.entries, req->res.headers.entries,
- sizeof(req->res.headers.entries[0]) * req->res.headers.size);
- req->res.original.headers.size = req->res.headers.size;
-}
-
-void h2o_init_request(h2o_req_t *req, h2o_conn_t *conn, h2o_req_t *src)
-{
- /* clear all memory (expect memory pool, since it is large) */
- memset(req, 0, offsetof(h2o_req_t, pool));
-
- /* init memory pool (before others, since it may be used) */
- h2o_mem_init_pool(&req->pool);
-
- /* init properties that should be initialized to non-zero */
- req->conn = conn;
- req->_timeout_entry.cb = deferred_proceed_cb;
- req->res.reason = "OK"; /* default to "OK" regardless of the status value, it's not important after all (never sent in HTTP2) */
- req->res.content_length = SIZE_MAX;
- req->preferred_chunk_size = SIZE_MAX;
-
- if (src != NULL) {
- size_t i;
-#define COPY(buf) \
- do { \
- req->buf.base = h2o_mem_alloc_pool(&req->pool, src->buf.len); \
- memcpy(req->buf.base, src->buf.base, src->buf.len); \
- req->buf.len = src->buf.len; \
- } while (0)
- COPY(input.authority);
- COPY(input.method);
- COPY(input.path);
- req->input.scheme = src->input.scheme;
- req->version = src->version;
- req->entity = src->entity;
- req->http1_is_persistent = src->http1_is_persistent;
- req->timestamps = src->timestamps;
- if (src->upgrade.base != NULL) {
- COPY(upgrade);
- } else {
- req->upgrade.base = NULL;
- req->upgrade.len = 0;
- }
-#undef COPY
- h2o_vector_reserve(&req->pool, &req->headers, src->headers.size);
- req->headers.size = src->headers.size;
- for (i = 0; i != src->headers.size; ++i) {
- h2o_header_t *dst_header = req->headers.entries + i, *src_header = src->headers.entries + i;
- if (h2o_iovec_is_token(src_header->name)) {
- dst_header->name = src_header->name;
- } else {
- dst_header->name = h2o_mem_alloc_pool(&req->pool, sizeof(*dst_header->name));
- *dst_header->name = h2o_strdup(&req->pool, src_header->name->base, src_header->name->len);
- }
- dst_header->value = h2o_strdup(&req->pool, src_header->value.base, src_header->value.len);
- if (!src_header->orig_name)
- dst_header->orig_name = NULL;
- else
- dst_header->orig_name = h2o_strdup(&req->pool, src_header->orig_name, src_header->name->len).base;
- }
- if (src->env.size != 0) {
- h2o_vector_reserve(&req->pool, &req->env, src->env.size);
- req->env.size = src->env.size;
- for (i = 0; i != req->env.size; ++i)
- req->env.entries[i] = h2o_strdup(&req->pool, src->env.entries[i].base, src->env.entries[i].len);
- }
- }
-}
-
-void h2o_dispose_request(h2o_req_t *req)
-{
- close_generator_and_filters(req);
-
- h2o_timeout_unlink(&req->_timeout_entry);
-
- if (req->version != 0 && req->pathconf != NULL) {
- h2o_logger_t **logger = req->pathconf->loggers.entries, **end = logger + req->pathconf->loggers.size;
- for (; logger != end; ++logger) {
- (*logger)->log_access((*logger), req);
- }
- }
-
- h2o_mem_clear_pool(&req->pool);
-}
-
-void h2o_process_request(h2o_req_t *req)
-{
- h2o_hostconf_t *hostconf = setup_before_processing(req);
- process_hosted_request(req, hostconf);
-}
-
-void h2o_delegate_request(h2o_req_t *req, h2o_handler_t *current_handler)
-{
- h2o_handler_t **handler = req->pathconf->handlers.entries, **end = handler + req->pathconf->handlers.size;
-
- for (; handler != end; ++handler) {
- if (*handler == current_handler) {
- ++handler;
- break;
- }
- }
- call_handlers(req, handler);
-}
-
-static void on_delegate_request_cb(h2o_timeout_entry_t *entry)
-{
- struct st_delegate_request_deferred_t *args =
- H2O_STRUCT_FROM_MEMBER(struct st_delegate_request_deferred_t, super.timeout, entry);
- h2o_delegate_request(args->super.req, args->current_handler);
-}
-
-void h2o_delegate_request_deferred(h2o_req_t *req, h2o_handler_t *current_handler)
-{
- struct st_delegate_request_deferred_t *args =
- (struct st_delegate_request_deferred_t *)create_deferred_action(req, sizeof(*args), on_delegate_request_cb);
- args->current_handler = current_handler;
-}
-
-void h2o_reprocess_request(h2o_req_t *req, h2o_iovec_t method, const h2o_url_scheme_t *scheme, h2o_iovec_t authority,
- h2o_iovec_t path, h2o_req_overrides_t *overrides, int is_delegated)
-{
- h2o_hostconf_t *hostconf;
-
- retain_original_response(req);
-
- /* close generators and filters that are already running */
- close_generator_and_filters(req);
-
- /* setup the request/response parameters */
- req->method = method;
- req->scheme = scheme;
- req->authority = authority;
- req->path = path;
- req->path_normalized = h2o_url_normalize_path(&req->pool, req->path.base, req->path.len, &req->query_at, &req->norm_indexes);
- req->overrides = overrides;
- req->res_is_delegated |= is_delegated;
- reset_response(req);
-
- /* check the delegation (or reprocess) counter */
- if (req->res_is_delegated) {
- if (req->num_delegated == req->conn->ctx->globalconf->max_delegations) {
- /* TODO log */
- h2o_send_error_502(req, "Gateway Error", "too many internal delegations", 0);
- return;
- }
- ++req->num_delegated;
- } else {
- if (req->num_reprocessed >= 5) {
- /* TODO log */
- h2o_send_error_502(req, "Gateway Error", "too many internal reprocesses", 0);
- return;
- }
- ++req->num_reprocessed;
- }
-
- /* handle the response using the handlers, if hostconf exists */
- h2o_hostconf_t **hosts = is_delegated ? req->conn->ctx->globalconf->hosts : req->conn->hosts;
- if (req->overrides == NULL && (hostconf = find_hostconf(hosts, req->authority, req->scheme->default_port)) != NULL) {
- req->pathconf = NULL;
- process_hosted_request(req, hostconf);
- return;
- }
-
- /* uses the current pathconf, in other words, proxy uses the previous pathconf for building filters */
- h2o__proxy_process_request(req);
-}
-
-static void on_reprocess_request_cb(h2o_timeout_entry_t *entry)
-{
- struct st_reprocess_request_deferred_t *args =
- H2O_STRUCT_FROM_MEMBER(struct st_reprocess_request_deferred_t, super.timeout, entry);
- h2o_reprocess_request(args->super.req, args->method, args->scheme, args->authority, args->path, args->overrides,
- args->is_delegated);
-}
-
-void h2o_reprocess_request_deferred(h2o_req_t *req, h2o_iovec_t method, const h2o_url_scheme_t *scheme, h2o_iovec_t authority,
- h2o_iovec_t path, h2o_req_overrides_t *overrides, int is_delegated)
-{
- struct st_reprocess_request_deferred_t *args =
- (struct st_reprocess_request_deferred_t *)create_deferred_action(req, sizeof(*args), on_reprocess_request_cb);
- args->method = method;
- args->scheme = scheme;
- args->authority = authority;
- args->path = path;
- args->overrides = overrides;
- args->is_delegated = is_delegated;
-}
-
-void h2o_start_response(h2o_req_t *req, h2o_generator_t *generator)
-{
- retain_original_response(req);
-
- /* set generator */
- assert(req->_generator == NULL);
- req->_generator = generator;
-
- /* setup response filters */
- if (req->prefilters != NULL) {
- req->prefilters->on_setup_ostream(req->prefilters, req, &req->_ostr_top);
- } else {
- h2o_setup_next_ostream(req, &req->_ostr_top);
- }
-}
-
-void h2o_send(h2o_req_t *req, h2o_iovec_t *bufs, size_t bufcnt, h2o_send_state_t state)
-{
- assert(req->_generator != NULL);
-
- if (!h2o_send_state_is_in_progress(state))
- req->_generator = NULL;
-
- req->_ostr_top->do_send(req->_ostr_top, req, bufs, bufcnt, state);
-}
-
-h2o_req_prefilter_t *h2o_add_prefilter(h2o_req_t *req, size_t sz)
-{
- h2o_req_prefilter_t *prefilter = h2o_mem_alloc_pool(&req->pool, sz);
- prefilter->next = req->prefilters;
- req->prefilters = prefilter;
- return prefilter;
-}
-
-h2o_ostream_t *h2o_add_ostream(h2o_req_t *req, size_t sz, h2o_ostream_t **slot)
-{
- h2o_ostream_t *ostr = h2o_mem_alloc_pool(&req->pool, sz);
- ostr->next = *slot;
- ostr->do_send = NULL;
- ostr->stop = NULL;
- ostr->start_pull = NULL;
-
- *slot = ostr;
-
- return ostr;
-}
-
-static void apply_env(h2o_req_t *req, h2o_envconf_t *env)
-{
- size_t i;
-
- if (env->parent != NULL)
- apply_env(req, env->parent);
- for (i = 0; i != env->unsets.size; ++i)
- h2o_req_unsetenv(req, env->unsets.entries[i].base, env->unsets.entries[i].len);
- for (i = 0; i != env->sets.size; i += 2)
- *h2o_req_getenv(req, env->sets.entries[i].base, env->sets.entries[i].len, 1) = env->sets.entries[i + 1];
-}
-
-void h2o_req_bind_conf(h2o_req_t *req, h2o_hostconf_t *hostconf, h2o_pathconf_t *pathconf)
-{
- req->hostconf = hostconf;
- req->pathconf = pathconf;
- if (pathconf->env != NULL)
- apply_env(req, pathconf->env);
-}
-
-void h2o_ostream_send_next(h2o_ostream_t *ostream, h2o_req_t *req, h2o_iovec_t *bufs, size_t bufcnt, h2o_send_state_t state)
-{
- if (!h2o_send_state_is_in_progress(state)) {
- assert(req->_ostr_top == ostream);
- req->_ostr_top = ostream->next;
- } else if (bufcnt == 0) {
- h2o_timeout_link(req->conn->ctx->loop, &req->conn->ctx->zero_timeout, &req->_timeout_entry);
- return;
- }
- ostream->next->do_send(ostream->next, req, bufs, bufcnt, state);
-}
-
-void h2o_req_fill_mime_attributes(h2o_req_t *req)
-{
- ssize_t content_type_index;
- h2o_mimemap_type_t *mime;
-
- if (req->res.mime_attr != NULL)
- return;
-
- if ((content_type_index = h2o_find_header(&req->res.headers, H2O_TOKEN_CONTENT_TYPE, -1)) != -1 &&
- (mime = h2o_mimemap_get_type_by_mimetype(req->pathconf->mimemap, req->res.headers.entries[content_type_index].value, 0)) !=
- NULL)
- req->res.mime_attr = &mime->data.attr;
- else
- req->res.mime_attr = &h2o_mime_attributes_as_is;
-}
-
-void h2o_send_inline(h2o_req_t *req, const char *body, size_t len)
-{
- static h2o_generator_t generator = {NULL, NULL};
-
- h2o_iovec_t buf = h2o_strdup(&req->pool, body, len);
- /* the function intentionally does not set the content length, since it may be used for generating 304 response, etc. */
- /* req->res.content_length = buf.len; */
-
- h2o_start_response(req, &generator);
-
- if (h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("HEAD")))
- h2o_send(req, NULL, 0, H2O_SEND_STATE_FINAL);
- else
- h2o_send(req, &buf, 1, H2O_SEND_STATE_FINAL);
-}
-
-void h2o_send_error_generic(h2o_req_t *req, int status, const char *reason, const char *body, int flags)
-{
- if (req->pathconf == NULL) {
- h2o_hostconf_t *hostconf = setup_before_processing(req);
- h2o_req_bind_conf(req, hostconf, &hostconf->fallback_path);
- }
-
- if ((flags & H2O_SEND_ERROR_HTTP1_CLOSE_CONNECTION) != 0)
- req->http1_is_persistent = 0;
-
- req->res.status = status;
- req->res.reason = reason;
- req->res.content_length = strlen(body);
-
- if ((flags & H2O_SEND_ERROR_KEEP_HEADERS) == 0)
- memset(&req->res.headers, 0, sizeof(req->res.headers));
-
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, NULL, H2O_STRLIT("text/plain; charset=utf-8"));
-
- h2o_send_inline(req, body, SIZE_MAX);
-}
-
-#define DECL_SEND_ERROR_DEFERRED(status_) \
- static void send_error_deferred_cb_##status_(h2o_timeout_entry_t *entry) \
- { \
- struct st_send_error_deferred_t *args = H2O_STRUCT_FROM_MEMBER(struct st_send_error_deferred_t, _timeout, entry); \
- reset_response(args->req); \
- args->req->conn->ctx->emitted_error_status[H2O_STATUS_ERROR_##status_]++; \
- h2o_send_error_generic(args->req, args->status, args->reason, args->body, args->flags); \
- } \
- \
- static void h2o_send_error_deferred_##status_(h2o_req_t *req, const char *reason, const char *body, int flags) \
- { \
- struct st_send_error_deferred_t *args = h2o_mem_alloc_pool(&req->pool, sizeof(*args)); \
- *args = (struct st_send_error_deferred_t){req, status_, reason, body, flags}; \
- args->_timeout.cb = send_error_deferred_cb_##status_; \
- h2o_timeout_link(req->conn->ctx->loop, &req->conn->ctx->zero_timeout, &args->_timeout); \
- }
-
-DECL_SEND_ERROR_DEFERRED(502)
-
-#undef DECL_SEND_ERROR_DEFERRED
-
-void h2o_req_log_error(h2o_req_t *req, const char *module, const char *fmt, ...)
-{
-#define INITIAL_BUF_SIZE 256
-
- char *errbuf = h2o_mem_alloc_pool(&req->pool, INITIAL_BUF_SIZE);
- int errlen;
- va_list args;
-
- va_start(args, fmt);
- errlen = vsnprintf(errbuf, INITIAL_BUF_SIZE, fmt, args);
- va_end(args);
-
- if (errlen >= INITIAL_BUF_SIZE) {
- errbuf = h2o_mem_alloc_pool(&req->pool, errlen + 1);
- va_start(args, fmt);
- errlen = vsnprintf(errbuf, errlen + 1, fmt, args);
- va_end(args);
- }
-
-#undef INITIAL_BUF_SIZE
-
- /* save the log */
- h2o_vector_reserve(&req->pool, &req->error_logs, req->error_logs.size + 1);
- req->error_logs.entries[req->error_logs.size++] = (h2o_req_error_log_t){module, h2o_iovec_init(errbuf, errlen)};
-
- if (req->pathconf->error_log.emit_request_errors) {
- /* build prefix */
- char *prefix = alloca(sizeof("[] in request::") + 32 + strlen(module)), *p = prefix;
- p += sprintf(p, "[%s] in request:", module);
- if (req->path.len < 32) {
- memcpy(p, req->path.base, req->path.len);
- p += req->path.len;
- } else {
- memcpy(p, req->path.base, 29);
- p += 29;
- memcpy(p, "...", 3);
- p += 3;
- }
- *p++ = ':';
- /* use writev(2) to emit error atomically */
- struct iovec vecs[] = {{prefix, p - prefix}, {errbuf, errlen}, {"\n", 1}};
- H2O_BUILD_ASSERT(sizeof(vecs) / sizeof(vecs[0]) < IOV_MAX);
- writev(2, vecs, sizeof(vecs) / sizeof(vecs[0]));
- }
-}
-
-void h2o_send_redirect(h2o_req_t *req, int status, const char *reason, const char *url, size_t url_len)
-{
- if (req->res_is_delegated) {
- h2o_iovec_t method = h2o_get_redirect_method(req->method, status);
- h2o_send_redirect_internal(req, method, url, url_len, 0);
- return;
- }
-
- static h2o_generator_t generator = {NULL, NULL};
- static const h2o_iovec_t body_prefix = {H2O_STRLIT("<!DOCTYPE html><TITLE>Moved</TITLE><P>The document has moved <A HREF=\"")};
- static const h2o_iovec_t body_suffix = {H2O_STRLIT("\">here</A>")};
-
- /* build and send response */
- h2o_iovec_t bufs[3];
- size_t bufcnt;
- if (h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("HEAD"))) {
- req->res.content_length = SIZE_MAX;
- bufcnt = 0;
- } else {
- bufs[0] = body_prefix;
- bufs[1] = h2o_htmlescape(&req->pool, url, url_len);
- bufs[2] = body_suffix;
- bufcnt = 3;
- req->res.content_length = body_prefix.len + bufs[1].len + body_suffix.len;
- }
- req->res.status = status;
- req->res.reason = reason;
- req->res.headers = (h2o_headers_t){NULL};
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_LOCATION, NULL, url, url_len);
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, NULL, H2O_STRLIT("text/html; charset=utf-8"));
- h2o_start_response(req, &generator);
- h2o_send(req, bufs, bufcnt, H2O_SEND_STATE_FINAL);
-}
-
-void h2o_send_redirect_internal(h2o_req_t *req, h2o_iovec_t method, const char *url_str, size_t url_len, int preserve_overrides)
-{
- h2o_url_t url;
-
- /* parse the location URL */
- if (h2o_url_parse_relative(url_str, url_len, &url) != 0) {
- /* TODO log fprintf(stderr, "[proxy] cannot handle location header: %.*s\n", (int)url_len, url); */
- h2o_send_error_deferred_502(req, "Gateway Error", "internal error", 0);
- return;
- }
- /* convert the location to absolute (while creating copies of the values passed to the deferred call) */
- if (url.scheme == NULL)
- url.scheme = req->scheme;
- if (url.authority.base == NULL) {
- if (req->hostconf != NULL)
- url.authority = req->hostconf->authority.hostport;
- else
- url.authority = req->authority;
- } else {
- if (h2o_lcstris(url.authority.base, url.authority.len, req->authority.base, req->authority.len)) {
- url.authority = req->authority;
- } else {
- url.authority = h2o_strdup(&req->pool, url.authority.base, url.authority.len);
- preserve_overrides = 0;
- }
- }
- h2o_iovec_t base_path = req->path;
- h2o_url_resolve_path(&base_path, &url.path);
- url.path = h2o_concat(&req->pool, base_path, url.path);
-
- h2o_reprocess_request_deferred(req, method, url.scheme, url.authority, url.path, preserve_overrides ? req->overrides : NULL, 1);
-}
-
-h2o_iovec_t h2o_get_redirect_method(h2o_iovec_t method, int status)
-{
- if (h2o_memis(method.base, method.len, H2O_STRLIT("POST")) && !(status == 307 || status == 308))
- method = h2o_iovec_init(H2O_STRLIT("GET"));
- return method;
-}
-
-h2o_iovec_t h2o_push_path_in_link_header(h2o_req_t *req, const char *value, size_t value_len)
-{
- int i;
- h2o_iovec_t ret = h2o_iovec_init(value, value_len);
- if (req->conn->callbacks->push_path == NULL)
- return ret;
-
- h2o_iovec_vector_t paths = h2o_extract_push_path_from_link_header(
- &req->pool, value, value_len, req->path_normalized, req->input.scheme, req->input.authority,
- req->res_is_delegated ? req->scheme : NULL, req->res_is_delegated ? &req->authority : NULL, &ret);
- if (paths.size == 0)
- return ret;
-
- for (i = 0; i < paths.size; i++) {
- req->conn->callbacks->push_path(req, paths.entries[i].base, paths.entries[i].len);
- }
- return ret;
-}
diff --git a/web/server/h2o/libh2o/lib/core/token.c b/web/server/h2o/libh2o/lib/core/token.c
deleted file mode 100644
index e21ce2383..000000000
--- a/web/server/h2o/libh2o/lib/core/token.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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 "h2o.h"
-#include "token_table.h"
-
-int h2o_iovec_is_token(const h2o_iovec_t *buf)
-{
- return &h2o__tokens[0].buf <= buf && buf <= &h2o__tokens[H2O_MAX_TOKENS - 1].buf;
-}
diff --git a/web/server/h2o/libh2o/lib/core/token_table.h b/web/server/h2o/libh2o/lib/core/token_table.h
deleted file mode 100644
index ae26aa6c4..000000000
--- a/web/server/h2o/libh2o/lib/core/token_table.h
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * 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 &quot;Software&quot;), 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 &quot;AS IS&quot;, 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.
- */
-
-/* DO NOT EDIT! generated by tokens.pl */
-h2o_token_t h2o__tokens[] = {{{H2O_STRLIT(":authority")}, 1, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT(":method")}, 2, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT(":path")}, 4, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT(":scheme")}, 6, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT(":status")}, 8, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("accept")}, 19, 0, 0, 0, 0, 1, 0},
- {{H2O_STRLIT("accept-charset")}, 15, 0, 0, 0, 0, 1, 0},
- {{H2O_STRLIT("accept-encoding")}, 16, 0, 0, 0, 0, 1, 0},
- {{H2O_STRLIT("accept-language")}, 17, 0, 0, 0, 0, 1, 0},
- {{H2O_STRLIT("accept-ranges")}, 18, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("access-control-allow-origin")}, 20, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("age")}, 21, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("allow")}, 22, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("authorization")}, 23, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("cache-control")}, 24, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("cache-digest")}, 0, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("connection")}, 0, 1, 1, 0, 1, 0, 0},
- {{H2O_STRLIT("content-disposition")}, 25, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("content-encoding")}, 26, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("content-language")}, 27, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("content-length")}, 28, 0, 0, 1, 0, 0, 0},
- {{H2O_STRLIT("content-location")}, 29, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("content-range")}, 30, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("content-type")}, 31, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("cookie")}, 32, 0, 0, 0, 0, 0, 1},
- {{H2O_STRLIT("date")}, 33, 0, 1, 0, 0, 0, 0},
- {{H2O_STRLIT("etag")}, 34, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("expect")}, 35, 0, 0, 1, 0, 0, 0},
- {{H2O_STRLIT("expires")}, 36, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("from")}, 37, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("host")}, 38, 0, 0, 1, 1, 0, 0},
- {{H2O_STRLIT("http2-settings")}, 0, 1, 0, 0, 1, 0, 0},
- {{H2O_STRLIT("if-match")}, 39, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("if-modified-since")}, 40, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("if-none-match")}, 41, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("if-range")}, 42, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("if-unmodified-since")}, 43, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("keep-alive")}, 0, 1, 1, 0, 0, 0, 0},
- {{H2O_STRLIT("last-modified")}, 44, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("link")}, 45, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("location")}, 46, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("max-forwards")}, 47, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("proxy-authenticate")}, 48, 1, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("proxy-authorization")}, 49, 1, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("range")}, 50, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("referer")}, 51, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("refresh")}, 52, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("retry-after")}, 53, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("server")}, 54, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("set-cookie")}, 55, 0, 0, 0, 0, 0, 1},
- {{H2O_STRLIT("strict-transport-security")}, 56, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("te")}, 0, 1, 0, 0, 1, 0, 0},
- {{H2O_STRLIT("transfer-encoding")}, 57, 1, 1, 1, 1, 0, 0},
- {{H2O_STRLIT("upgrade")}, 0, 1, 1, 1, 1, 0, 0},
- {{H2O_STRLIT("user-agent")}, 58, 0, 0, 0, 0, 1, 0},
- {{H2O_STRLIT("vary")}, 59, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("via")}, 60, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("www-authenticate")}, 61, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("x-compress-hint")}, 0, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("x-forwarded-for")}, 0, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("x-reproxy-url")}, 0, 0, 0, 0, 0, 0, 0},
- {{H2O_STRLIT("x-traffic")}, 0, 0, 0, 0, 0, 0, 0}};
-size_t h2o__num_tokens = 62;
-
-const h2o_token_t *h2o_lookup_token(const char *name, size_t len)
-{
- switch (len) {
- case 2:
- switch (name[1]) {
- case 'e':
- if (memcmp(name, "t", 1) == 0)
- return H2O_TOKEN_TE;
- break;
- }
- break;
- case 3:
- switch (name[2]) {
- case 'a':
- if (memcmp(name, "vi", 2) == 0)
- return H2O_TOKEN_VIA;
- break;
- case 'e':
- if (memcmp(name, "ag", 2) == 0)
- return H2O_TOKEN_AGE;
- break;
- }
- break;
- case 4:
- switch (name[3]) {
- case 'e':
- if (memcmp(name, "dat", 3) == 0)
- return H2O_TOKEN_DATE;
- break;
- case 'g':
- if (memcmp(name, "eta", 3) == 0)
- return H2O_TOKEN_ETAG;
- break;
- case 'k':
- if (memcmp(name, "lin", 3) == 0)
- return H2O_TOKEN_LINK;
- break;
- case 'm':
- if (memcmp(name, "fro", 3) == 0)
- return H2O_TOKEN_FROM;
- break;
- case 't':
- if (memcmp(name, "hos", 3) == 0)
- return H2O_TOKEN_HOST;
- break;
- case 'y':
- if (memcmp(name, "var", 3) == 0)
- return H2O_TOKEN_VARY;
- break;
- }
- break;
- case 5:
- switch (name[4]) {
- case 'e':
- if (memcmp(name, "rang", 4) == 0)
- return H2O_TOKEN_RANGE;
- break;
- case 'h':
- if (memcmp(name, ":pat", 4) == 0)
- return H2O_TOKEN_PATH;
- break;
- case 'w':
- if (memcmp(name, "allo", 4) == 0)
- return H2O_TOKEN_ALLOW;
- break;
- }
- break;
- case 6:
- switch (name[5]) {
- case 'e':
- if (memcmp(name, "cooki", 5) == 0)
- return H2O_TOKEN_COOKIE;
- break;
- case 'r':
- if (memcmp(name, "serve", 5) == 0)
- return H2O_TOKEN_SERVER;
- break;
- case 't':
- if (memcmp(name, "accep", 5) == 0)
- return H2O_TOKEN_ACCEPT;
- if (memcmp(name, "expec", 5) == 0)
- return H2O_TOKEN_EXPECT;
- break;
- }
- break;
- case 7:
- switch (name[6]) {
- case 'd':
- if (memcmp(name, ":metho", 6) == 0)
- return H2O_TOKEN_METHOD;
- break;
- case 'e':
- if (memcmp(name, ":schem", 6) == 0)
- return H2O_TOKEN_SCHEME;
- if (memcmp(name, "upgrad", 6) == 0)
- return H2O_TOKEN_UPGRADE;
- break;
- case 'h':
- if (memcmp(name, "refres", 6) == 0)
- return H2O_TOKEN_REFRESH;
- break;
- case 'r':
- if (memcmp(name, "refere", 6) == 0)
- return H2O_TOKEN_REFERER;
- break;
- case 's':
- if (memcmp(name, ":statu", 6) == 0)
- return H2O_TOKEN_STATUS;
- if (memcmp(name, "expire", 6) == 0)
- return H2O_TOKEN_EXPIRES;
- break;
- }
- break;
- case 8:
- switch (name[7]) {
- case 'e':
- if (memcmp(name, "if-rang", 7) == 0)
- return H2O_TOKEN_IF_RANGE;
- break;
- case 'h':
- if (memcmp(name, "if-matc", 7) == 0)
- return H2O_TOKEN_IF_MATCH;
- break;
- case 'n':
- if (memcmp(name, "locatio", 7) == 0)
- return H2O_TOKEN_LOCATION;
- break;
- }
- break;
- case 9:
- switch (name[8]) {
- case 'c':
- if (memcmp(name, "x-traffi", 8) == 0)
- return H2O_TOKEN_X_TRAFFIC;
- break;
- }
- break;
- case 10:
- switch (name[9]) {
- case 'e':
- if (memcmp(name, "keep-aliv", 9) == 0)
- return H2O_TOKEN_KEEP_ALIVE;
- if (memcmp(name, "set-cooki", 9) == 0)
- return H2O_TOKEN_SET_COOKIE;
- break;
- case 'n':
- if (memcmp(name, "connectio", 9) == 0)
- return H2O_TOKEN_CONNECTION;
- break;
- case 't':
- if (memcmp(name, "user-agen", 9) == 0)
- return H2O_TOKEN_USER_AGENT;
- break;
- case 'y':
- if (memcmp(name, ":authorit", 9) == 0)
- return H2O_TOKEN_AUTHORITY;
- break;
- }
- break;
- case 11:
- switch (name[10]) {
- case 'r':
- if (memcmp(name, "retry-afte", 10) == 0)
- return H2O_TOKEN_RETRY_AFTER;
- break;
- }
- break;
- case 12:
- switch (name[11]) {
- case 'e':
- if (memcmp(name, "content-typ", 11) == 0)
- return H2O_TOKEN_CONTENT_TYPE;
- break;
- case 's':
- if (memcmp(name, "max-forward", 11) == 0)
- return H2O_TOKEN_MAX_FORWARDS;
- break;
- case 't':
- if (memcmp(name, "cache-diges", 11) == 0)
- return H2O_TOKEN_CACHE_DIGEST;
- break;
- }
- break;
- case 13:
- switch (name[12]) {
- case 'd':
- if (memcmp(name, "last-modifie", 12) == 0)
- return H2O_TOKEN_LAST_MODIFIED;
- break;
- case 'e':
- if (memcmp(name, "content-rang", 12) == 0)
- return H2O_TOKEN_CONTENT_RANGE;
- break;
- case 'h':
- if (memcmp(name, "if-none-matc", 12) == 0)
- return H2O_TOKEN_IF_NONE_MATCH;
- break;
- case 'l':
- if (memcmp(name, "cache-contro", 12) == 0)
- return H2O_TOKEN_CACHE_CONTROL;
- if (memcmp(name, "x-reproxy-ur", 12) == 0)
- return H2O_TOKEN_X_REPROXY_URL;
- break;
- case 'n':
- if (memcmp(name, "authorizatio", 12) == 0)
- return H2O_TOKEN_AUTHORIZATION;
- break;
- case 's':
- if (memcmp(name, "accept-range", 12) == 0)
- return H2O_TOKEN_ACCEPT_RANGES;
- break;
- }
- break;
- case 14:
- switch (name[13]) {
- case 'h':
- if (memcmp(name, "content-lengt", 13) == 0)
- return H2O_TOKEN_CONTENT_LENGTH;
- break;
- case 's':
- if (memcmp(name, "http2-setting", 13) == 0)
- return H2O_TOKEN_HTTP2_SETTINGS;
- break;
- case 't':
- if (memcmp(name, "accept-charse", 13) == 0)
- return H2O_TOKEN_ACCEPT_CHARSET;
- break;
- }
- break;
- case 15:
- switch (name[14]) {
- case 'e':
- if (memcmp(name, "accept-languag", 14) == 0)
- return H2O_TOKEN_ACCEPT_LANGUAGE;
- break;
- case 'g':
- if (memcmp(name, "accept-encodin", 14) == 0)
- return H2O_TOKEN_ACCEPT_ENCODING;
- break;
- case 'r':
- if (memcmp(name, "x-forwarded-fo", 14) == 0)
- return H2O_TOKEN_X_FORWARDED_FOR;
- break;
- case 't':
- if (memcmp(name, "x-compress-hin", 14) == 0)
- return H2O_TOKEN_X_COMPRESS_HINT;
- break;
- }
- break;
- case 16:
- switch (name[15]) {
- case 'e':
- if (memcmp(name, "content-languag", 15) == 0)
- return H2O_TOKEN_CONTENT_LANGUAGE;
- if (memcmp(name, "www-authenticat", 15) == 0)
- return H2O_TOKEN_WWW_AUTHENTICATE;
- break;
- case 'g':
- if (memcmp(name, "content-encodin", 15) == 0)
- return H2O_TOKEN_CONTENT_ENCODING;
- break;
- case 'n':
- if (memcmp(name, "content-locatio", 15) == 0)
- return H2O_TOKEN_CONTENT_LOCATION;
- break;
- }
- break;
- case 17:
- switch (name[16]) {
- case 'e':
- if (memcmp(name, "if-modified-sinc", 16) == 0)
- return H2O_TOKEN_IF_MODIFIED_SINCE;
- break;
- case 'g':
- if (memcmp(name, "transfer-encodin", 16) == 0)
- return H2O_TOKEN_TRANSFER_ENCODING;
- break;
- }
- break;
- case 18:
- switch (name[17]) {
- case 'e':
- if (memcmp(name, "proxy-authenticat", 17) == 0)
- return H2O_TOKEN_PROXY_AUTHENTICATE;
- break;
- }
- break;
- case 19:
- switch (name[18]) {
- case 'e':
- if (memcmp(name, "if-unmodified-sinc", 18) == 0)
- return H2O_TOKEN_IF_UNMODIFIED_SINCE;
- break;
- case 'n':
- if (memcmp(name, "content-dispositio", 18) == 0)
- return H2O_TOKEN_CONTENT_DISPOSITION;
- if (memcmp(name, "proxy-authorizatio", 18) == 0)
- return H2O_TOKEN_PROXY_AUTHORIZATION;
- break;
- }
- break;
- case 25:
- switch (name[24]) {
- case 'y':
- if (memcmp(name, "strict-transport-securit", 24) == 0)
- return H2O_TOKEN_STRICT_TRANSPORT_SECURITY;
- break;
- }
- break;
- case 27:
- switch (name[26]) {
- case 'n':
- if (memcmp(name, "access-control-allow-origi", 26) == 0)
- return H2O_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
- break;
- }
- break;
- }
-
- return NULL;
-}
diff --git a/web/server/h2o/libh2o/lib/core/util.c b/web/server/h2o/libh2o/lib/core/util.c
deleted file mode 100644
index 50d2b2493..000000000
--- a/web/server/h2o/libh2o/lib/core/util.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Satoh Hiroh
- *
- * 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 <assert.h>
-#include <inttypes.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include "h2o.h"
-#include "h2o/http1.h"
-#include "h2o/http2.h"
-
-struct st_h2o_accept_data_t {
- h2o_accept_ctx_t *ctx;
- h2o_socket_t *sock;
- h2o_timeout_entry_t timeout;
- h2o_memcached_req_t *async_resumption_get_req;
- struct timeval connected_at;
-};
-
-static void on_accept_timeout(h2o_timeout_entry_t *entry);
-
-static struct st_h2o_accept_data_t *create_accept_data(h2o_accept_ctx_t *ctx, h2o_socket_t *sock, struct timeval connected_at)
-{
- struct st_h2o_accept_data_t *data = h2o_mem_alloc(sizeof(*data));
-
- data->ctx = ctx;
- data->sock = sock;
- data->timeout = (h2o_timeout_entry_t){0};
- data->timeout.cb = on_accept_timeout;
- h2o_timeout_link(ctx->ctx->loop, &ctx->ctx->handshake_timeout, &data->timeout);
- data->async_resumption_get_req = NULL;
- data->connected_at = connected_at;
-
- sock->data = data;
- return data;
-}
-
-static void free_accept_data(struct st_h2o_accept_data_t *data)
-{
- assert(data->async_resumption_get_req == NULL);
- h2o_timeout_unlink(&data->timeout);
- free(data);
-}
-
-static struct {
- h2o_memcached_context_t *memc;
- unsigned expiration;
-} async_resumption_context;
-
-static void async_resumption_on_get(h2o_iovec_t session_data, void *_accept_data)
-{
- struct st_h2o_accept_data_t *accept_data = _accept_data;
- accept_data->async_resumption_get_req = NULL;
- h2o_socket_ssl_resume_server_handshake(accept_data->sock, session_data);
-}
-
-static void async_resumption_get(h2o_socket_t *sock, h2o_iovec_t session_id)
-{
- struct st_h2o_accept_data_t *data = sock->data;
-
- data->async_resumption_get_req =
- h2o_memcached_get(async_resumption_context.memc, data->ctx->libmemcached_receiver, session_id, async_resumption_on_get,
- data, H2O_MEMCACHED_ENCODE_KEY | H2O_MEMCACHED_ENCODE_VALUE);
-}
-
-static void async_resumption_new(h2o_iovec_t session_id, h2o_iovec_t session_data)
-{
- h2o_memcached_set(async_resumption_context.memc, session_id, session_data,
- (uint32_t)time(NULL) + async_resumption_context.expiration,
- H2O_MEMCACHED_ENCODE_KEY | H2O_MEMCACHED_ENCODE_VALUE);
-}
-
-void h2o_accept_setup_async_ssl_resumption(h2o_memcached_context_t *memc, unsigned expiration)
-{
- async_resumption_context.memc = memc;
- async_resumption_context.expiration = expiration;
- h2o_socket_ssl_async_resumption_init(async_resumption_get, async_resumption_new);
-}
-
-void on_accept_timeout(h2o_timeout_entry_t *entry)
-{
- /* TODO log */
- struct st_h2o_accept_data_t *data = H2O_STRUCT_FROM_MEMBER(struct st_h2o_accept_data_t, timeout, entry);
- if (data->async_resumption_get_req != NULL) {
- h2o_memcached_cancel_get(async_resumption_context.memc, data->async_resumption_get_req);
- data->async_resumption_get_req = NULL;
- }
- h2o_socket_t *sock = data->sock;
- free_accept_data(data);
- h2o_socket_close(sock);
-}
-
-static void on_ssl_handshake_complete(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_accept_data_t *data = sock->data;
- sock->data = NULL;
-
- if (err != NULL) {
- h2o_socket_close(sock);
- goto Exit;
- }
-
- h2o_iovec_t proto = h2o_socket_ssl_get_selected_protocol(sock);
- const h2o_iovec_t *ident;
- for (ident = h2o_http2_alpn_protocols; ident->len != 0; ++ident) {
- if (proto.len == ident->len && memcmp(proto.base, ident->base, proto.len) == 0) {
- /* connect as http2 */
- h2o_http2_accept(data->ctx, sock, data->connected_at);
- goto Exit;
- }
- }
- /* connect as http1 */
- h2o_http1_accept(data->ctx, sock, data->connected_at);
-
-Exit:
- free_accept_data(data);
-}
-
-static ssize_t parse_proxy_line(char *src, size_t len, struct sockaddr *sa, socklen_t *salen)
-{
-#define CHECK_EOF() \
- if (p == end) \
- return -2
-#define EXPECT_CHAR(ch) \
- do { \
- CHECK_EOF(); \
- if (*p++ != ch) \
- return -1; \
- } while (0)
-#define SKIP_TO_WS() \
- do { \
- do { \
- CHECK_EOF(); \
- } while (*p++ != ' '); \
- --p; \
- } while (0)
-
- char *p = src, *end = p + len;
- void *addr;
- in_port_t *port;
-
- /* "PROXY "*/
- EXPECT_CHAR('P');
- EXPECT_CHAR('R');
- EXPECT_CHAR('O');
- EXPECT_CHAR('X');
- EXPECT_CHAR('Y');
- EXPECT_CHAR(' ');
-
- /* "TCP[46] " */
- CHECK_EOF();
- if (*p++ != 'T') {
- *salen = 0; /* indicate that no data has been obtained */
- goto SkipToEOL;
- }
- EXPECT_CHAR('C');
- EXPECT_CHAR('P');
- CHECK_EOF();
- switch (*p++) {
- case '4':
- *salen = sizeof(struct sockaddr_in);
- memset(sa, 0, sizeof(struct sockaddr_in));
- sa->sa_family = AF_INET;
- addr = &((struct sockaddr_in *)sa)->sin_addr;
- port = &((struct sockaddr_in *)sa)->sin_port;
- break;
- case '6':
- *salen = sizeof(struct sockaddr_in6);
- memset(sa, 0, sizeof(struct sockaddr_in6));
- sa->sa_family = AF_INET6;
- addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
- port = &((struct sockaddr_in6 *)sa)->sin6_port;
- break;
- default:
- return -1;
- }
- EXPECT_CHAR(' ');
-
- /* parse peer address */
- char *addr_start = p;
- SKIP_TO_WS();
- *p = '\0';
- if (inet_pton(sa->sa_family, addr_start, addr) != 1)
- return -1;
- *p++ = ' ';
-
- /* skip local address */
- SKIP_TO_WS();
- ++p;
-
- /* parse peer port */
- char *port_start = p;
- SKIP_TO_WS();
- *p = '\0';
- unsigned short usval;
- if (sscanf(port_start, "%hu", &usval) != 1)
- return -1;
- *port = htons(usval);
- *p++ = ' ';
-
-SkipToEOL:
- do {
- CHECK_EOF();
- } while (*p++ != '\r');
- CHECK_EOF();
- if (*p++ != '\n')
- return -2;
- return p - src;
-
-#undef CHECK_EOF
-#undef EXPECT_CHAR
-#undef SKIP_TO_WS
-}
-
-static void on_read_proxy_line(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_accept_data_t *data = sock->data;
-
- if (err != NULL) {
- free_accept_data(data);
- h2o_socket_close(sock);
- return;
- }
-
- struct sockaddr_storage addr;
- socklen_t addrlen;
- ssize_t r = parse_proxy_line(sock->input->bytes, sock->input->size, (void *)&addr, &addrlen);
- switch (r) {
- case -1: /* error, just pass the input to the next handler */
- break;
- case -2: /* incomplete */
- return;
- default:
- h2o_buffer_consume(&sock->input, r);
- if (addrlen != 0)
- h2o_socket_setpeername(sock, (void *)&addr, addrlen);
- break;
- }
-
- if (data->ctx->ssl_ctx != NULL) {
- h2o_socket_ssl_handshake(sock, data->ctx->ssl_ctx, NULL, on_ssl_handshake_complete);
- } else {
- struct st_h2o_accept_data_t *data = sock->data;
- sock->data = NULL;
- h2o_http1_accept(data->ctx, sock, data->connected_at);
- free_accept_data(data);
- }
-}
-
-void h2o_accept(h2o_accept_ctx_t *ctx, h2o_socket_t *sock)
-{
- struct timeval connected_at = *h2o_get_timestamp(ctx->ctx, NULL, NULL);
-
- if (ctx->expect_proxy_line || ctx->ssl_ctx != NULL) {
- create_accept_data(ctx, sock, connected_at);
- if (ctx->expect_proxy_line) {
- h2o_socket_read_start(sock, on_read_proxy_line);
- } else {
- h2o_socket_ssl_handshake(sock, ctx->ssl_ctx, NULL, on_ssl_handshake_complete);
- }
- } else {
- h2o_http1_accept(ctx, sock, connected_at);
- }
-}
-
-size_t h2o_stringify_protocol_version(char *dst, int version)
-{
- char *p = dst;
-
- if (version < 0x200) {
- assert(version <= 0x109);
-#define PREFIX "HTTP/1."
- memcpy(p, PREFIX, sizeof(PREFIX) - 1);
- p += sizeof(PREFIX) - 1;
-#undef PREFIX
- *p++ = '0' + (version & 0xff);
- } else {
-#define PROTO "HTTP/2"
- memcpy(p, PROTO, sizeof(PROTO) - 1);
- p += sizeof(PROTO) - 1;
-#undef PROTO
- }
-
- *p = '\0';
- return p - dst;
-}
-
-size_t h2o_stringify_proxy_header(h2o_conn_t *conn, char *buf)
-{
- struct sockaddr_storage ss;
- socklen_t sslen;
- size_t strlen;
- uint16_t peerport;
- char *dst = buf;
-
- if ((sslen = conn->callbacks->get_peername(conn, (void *)&ss)) == 0)
- goto Unknown;
- switch (ss.ss_family) {
- case AF_INET:
- memcpy(dst, "PROXY TCP4 ", 11);
- dst += 11;
- break;
- case AF_INET6:
- memcpy(dst, "PROXY TCP6 ", 11);
- dst += 11;
- break;
- default:
- goto Unknown;
- }
- if ((strlen = h2o_socket_getnumerichost((void *)&ss, sslen, dst)) == SIZE_MAX)
- goto Unknown;
- dst += strlen;
- *dst++ = ' ';
-
- peerport = h2o_socket_getport((void *)&ss);
-
- if ((sslen = conn->callbacks->get_sockname(conn, (void *)&ss)) == 0)
- goto Unknown;
- if ((strlen = h2o_socket_getnumerichost((void *)&ss, sslen, dst)) == SIZE_MAX)
- goto Unknown;
- dst += strlen;
- *dst++ = ' ';
-
- dst += sprintf(dst, "%" PRIu16 " %" PRIu16 "\r\n", peerport, (uint16_t)h2o_socket_getport((void *)&ss));
-
- return dst - buf;
-
-Unknown:
- memcpy(buf, "PROXY UNKNOWN\r\n", 15);
- return 15;
-}
-
-static void push_one_path(h2o_mem_pool_t *pool, h2o_iovec_vector_t *paths_to_push, h2o_iovec_t url, h2o_iovec_t base_path,
- const h2o_url_scheme_t *input_scheme, h2o_iovec_t input_authority, const h2o_url_scheme_t *base_scheme,
- h2o_iovec_t *base_authority)
-{
- h2o_url_t parsed, resolved;
-
- /* check the authority, and extract absolute path */
- if (h2o_url_parse_relative(url.base, url.len, &parsed) != 0)
- return;
-
- /* fast-path for abspath form */
- if (base_scheme == NULL && parsed.scheme == NULL && parsed.authority.base == NULL && url.len != 0 && url.base[0] == '/') {
- h2o_vector_reserve(pool, paths_to_push, paths_to_push->size + 1);
- paths_to_push->entries[paths_to_push->size++] = h2o_strdup(pool, url.base, url.len);
- return;
- }
-
- /* check scheme and authority if given URL contains either of the two, or if base is specified */
- h2o_url_t base = {input_scheme, input_authority, {NULL}, base_path, 65535};
- if (base_scheme != NULL) {
- base.scheme = base_scheme;
- base.authority = *base_authority;
- }
- h2o_url_resolve(pool, &base, &parsed, &resolved);
- if (input_scheme != resolved.scheme)
- return;
- if (!h2o_lcstris(input_authority.base, input_authority.len, resolved.authority.base, resolved.authority.len))
- return;
-
- h2o_vector_reserve(pool, paths_to_push, paths_to_push->size + 1);
- paths_to_push->entries[paths_to_push->size++] = resolved.path;
-}
-
-h2o_iovec_vector_t h2o_extract_push_path_from_link_header(h2o_mem_pool_t *pool, const char *value, size_t value_len,
- h2o_iovec_t base_path, const h2o_url_scheme_t *input_scheme,
- h2o_iovec_t input_authority, const h2o_url_scheme_t *base_scheme,
- h2o_iovec_t *base_authority, h2o_iovec_t *filtered_value)
-{
- h2o_iovec_vector_t paths_to_push = {NULL};
- h2o_iovec_t iter = h2o_iovec_init(value, value_len), token_value;
- const char *token;
- size_t token_len;
- *filtered_value = h2o_iovec_init(NULL, 0);
-
-#define PUSH_FILTERED_VALUE(s, e) \
- do { \
- if (filtered_value->len != 0) { \
- memcpy(filtered_value->base + filtered_value->len, ", ", 2); \
- filtered_value->len += 2; \
- } \
- memcpy(filtered_value->base + filtered_value->len, (s), (e) - (s)); \
- filtered_value->len += (e) - (s); \
- } while (0)
-
- /* extract URL values from Link: </pushed.css>; rel=preload */
- do {
- if ((token = h2o_next_token(&iter, ';', &token_len, NULL)) == NULL)
- break;
- /* first element should be <URL> */
- if (!(token_len >= 2 && token[0] == '<' && token[token_len - 1] == '>'))
- break;
- h2o_iovec_t url_with_brackets = h2o_iovec_init(token, token_len);
- /* find rel=preload */
- int preload = 0, nopush = 0, push_only = 0;
- while ((token = h2o_next_token(&iter, ';', &token_len, &token_value)) != NULL &&
- !h2o_memis(token, token_len, H2O_STRLIT(","))) {
- if (h2o_lcstris(token, token_len, H2O_STRLIT("rel")) &&
- h2o_lcstris(token_value.base, token_value.len, H2O_STRLIT("preload"))) {
- preload++;
- } else if (h2o_lcstris(token, token_len, H2O_STRLIT("nopush"))) {
- nopush++;
- } else if (h2o_lcstris(token, token_len, H2O_STRLIT("x-http2-push-only"))) {
- push_only++;
- }
- }
- /* push the path */
- if (!nopush && preload)
- push_one_path(pool, &paths_to_push, h2o_iovec_init(url_with_brackets.base + 1, url_with_brackets.len - 2), base_path,
- input_scheme, input_authority, base_scheme, base_authority);
- /* store the elements that needs to be preserved to filtered_value */
- if (push_only) {
- if (filtered_value->base == NULL) {
- /* the max. size of filtered_value would be x2 in the worst case, when "," is converted to ", " */
- filtered_value->base = h2o_mem_alloc_pool(pool, value_len * 2);
- const char *prev_comma = h2o_memrchr(value, ',', url_with_brackets.base - value);
- if (prev_comma != NULL)
- PUSH_FILTERED_VALUE(value, prev_comma);
- }
- } else if (filtered_value->base != NULL) {
- PUSH_FILTERED_VALUE(url_with_brackets.base, token != NULL ? token : value + value_len);
- }
- } while (token != NULL);
-
- if (filtered_value->base != NULL) {
- if (token != NULL)
- PUSH_FILTERED_VALUE(token, value + value_len);
- } else {
- *filtered_value = h2o_iovec_init(value, value_len);
- }
-
- return paths_to_push;
-
-#undef PUSH_FILTERED_VALUE
-}
-
-int h2o_get_compressible_types(const h2o_headers_t *headers)
-{
- size_t header_index;
- int compressible_types = 0;
-
- for (header_index = 0; header_index != headers->size; ++header_index) {
- const h2o_header_t *header = headers->entries + header_index;
- if (H2O_UNLIKELY(header->name == &H2O_TOKEN_ACCEPT_ENCODING->buf)) {
- h2o_iovec_t iter = h2o_iovec_init(header->value.base, header->value.len);
- const char *token = NULL;
- size_t token_len = 0;
- while ((token = h2o_next_token(&iter, ',', &token_len, NULL)) != NULL) {
- if (h2o_lcstris(token, token_len, H2O_STRLIT("gzip")))
- compressible_types |= H2O_COMPRESSIBLE_GZIP;
- else if (h2o_lcstris(token, token_len, H2O_STRLIT("br")))
- compressible_types |= H2O_COMPRESSIBLE_BROTLI;
- }
- }
- }
-
- return compressible_types;
-}
-
-h2o_iovec_t h2o_build_destination(h2o_req_t *req, const char *prefix, size_t prefix_len, int use_path_normalized)
-{
- h2o_iovec_t parts[4];
- size_t num_parts = 0;
- int conf_ends_with_slash = req->pathconf->path.base[req->pathconf->path.len - 1] == '/';
- int prefix_ends_with_slash = prefix[prefix_len - 1] == '/';
-
- /* destination starts with given prefix */
- parts[num_parts++] = h2o_iovec_init(prefix, prefix_len);
-
- /* make adjustments depending on the trailing slashes */
- if (conf_ends_with_slash != prefix_ends_with_slash) {
- if (conf_ends_with_slash) {
- parts[num_parts++] = h2o_iovec_init(H2O_STRLIT("/"));
- } else {
- if (req->path_normalized.len != req->pathconf->path.len)
- parts[num_parts - 1].len -= 1;
- }
- }
-
- /* append suffix path and query */
-
- if (use_path_normalized) {
- parts[num_parts++] = h2o_uri_escape(&req->pool, req->path_normalized.base + req->pathconf->path.len,
- req->path_normalized.len - req->pathconf->path.len, "/@:");
- if (req->query_at != SIZE_MAX) {
- parts[num_parts++] = h2o_iovec_init(req->path.base + req->query_at, req->path.len - req->query_at);
- }
- } else {
- if (req->path.len > 1) {
- /*
- * When proxying, we want to modify the input URL as little
- * as possible. We use norm_indexes to find the start of
- * the path we want to forward.
- */
- size_t next_unnormalized;
- if (req->norm_indexes && req->pathconf->path.len > 1) {
- next_unnormalized = req->norm_indexes[req->pathconf->path.len - 1];
- } else {
- next_unnormalized = req->pathconf->path.len;
- }
-
- /*
- * Special case: the input path didn't have any '/' including the first,
- * so the first character is actually found at '0'
- */
- if (req->path.base[0] != '/' && next_unnormalized == 1) {
- next_unnormalized = 0;
- }
- parts[num_parts++] = (h2o_iovec_t){req->path.base + next_unnormalized, req->path.len - next_unnormalized};
- }
- }
-
- return h2o_concat_list(&req->pool, parts, num_parts);
-}
-
-/* h2-14 and h2-16 are kept for backwards compatibility, as they are often used */
-#define ALPN_ENTRY(s) \
- { \
- H2O_STRLIT(s) \
- }
-#define ALPN_PROTOCOLS_CORE ALPN_ENTRY("h2"), ALPN_ENTRY("h2-16"), ALPN_ENTRY("h2-14")
-#define NPN_PROTOCOLS_CORE \
- "\x02" \
- "h2" \
- "\x05" \
- "h2-16" \
- "\x05" \
- "h2-14"
-
-static const h2o_iovec_t http2_alpn_protocols[] = {ALPN_PROTOCOLS_CORE, {NULL}};
-const h2o_iovec_t *h2o_http2_alpn_protocols = http2_alpn_protocols;
-
-static const h2o_iovec_t alpn_protocols[] = {ALPN_PROTOCOLS_CORE, {H2O_STRLIT("http/1.1")}, {NULL}};
-const h2o_iovec_t *h2o_alpn_protocols = alpn_protocols;
-
-const char *h2o_http2_npn_protocols = NPN_PROTOCOLS_CORE;
-const char *h2o_npn_protocols = NPN_PROTOCOLS_CORE "\x08"
- "http/1.1";
-
-uint64_t h2o_connection_id = 0;
diff --git a/web/server/h2o/libh2o/lib/handler/access_log.c b/web/server/h2o/libh2o/lib/handler/access_log.c
deleted file mode 100644
index 4a7704174..000000000
--- a/web/server/h2o/libh2o/lib/handler/access_log.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <spawn.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include "h2o.h"
-#include "h2o/serverutil.h"
-
-struct st_h2o_access_log_filehandle_t {
- h2o_logconf_t *logconf;
- int fd;
-};
-
-struct st_h2o_access_logger_t {
- h2o_logger_t super;
- h2o_access_log_filehandle_t *fh;
-};
-
-static void log_access(h2o_logger_t *_self, h2o_req_t *req)
-{
- struct st_h2o_access_logger_t *self = (struct st_h2o_access_logger_t *)_self;
- h2o_access_log_filehandle_t *fh = self->fh;
- char *logline, buf[4096];
- size_t len;
-
- /* stringify */
- len = sizeof(buf);
- logline = h2o_log_request(fh->logconf, req, &len, buf);
-
- /* emit */
- write(fh->fd, logline, len);
-
- /* free memory */
- if (logline != buf)
- free(logline);
-}
-
-static void on_dispose_handle(void *_fh)
-{
- h2o_access_log_filehandle_t *fh = _fh;
-
- h2o_logconf_dispose(fh->logconf);
- close(fh->fd);
-}
-
-int h2o_access_log_open_log(const char *path)
-{
- int fd;
-
- if (path[0] == '|') {
- int pipefds[2];
- pid_t pid;
- char *argv[4] = {"/bin/sh", "-c", (char *)(path + 1), NULL};
- /* create pipe */
- if (pipe(pipefds) != 0) {
- perror("pipe failed");
- return -1;
- }
- if (fcntl(pipefds[1], F_SETFD, FD_CLOEXEC) == -1) {
- perror("failed to set FD_CLOEXEC on pipefds[1]");
- return -1;
- }
- /* spawn the logger */
- int mapped_fds[] = {pipefds[0], 0, /* map pipefds[0] to stdin */
- -1};
- if ((pid = h2o_spawnp(argv[0], argv, mapped_fds, 0)) == -1) {
- fprintf(stderr, "failed to open logger: %s:%s\n", path + 1, strerror(errno));
- return -1;
- }
- /* close the read side of the pipefds and return the write side */
- close(pipefds[0]);
- fd = pipefds[1];
- } else {
- if ((fd = open(path, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0644)) == -1) {
- fprintf(stderr, "failed to open log file:%s:%s\n", path, strerror(errno));
- return -1;
- }
- }
-
- return fd;
-}
-
-h2o_access_log_filehandle_t *h2o_access_log_open_handle(const char *path, const char *fmt, int escape)
-{
- h2o_logconf_t *logconf;
- int fd;
- h2o_access_log_filehandle_t *fh;
- char errbuf[256];
-
- /* default to combined log format */
- if (fmt == NULL)
- fmt = "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\"";
- if ((logconf = h2o_logconf_compile(fmt, escape, errbuf)) == NULL) {
- fprintf(stderr, "%s\n", errbuf);
- return NULL;
- }
-
- /* open log file */
- if ((fd = h2o_access_log_open_log(path)) == -1) {
- h2o_logconf_dispose(logconf);
- return NULL;
- }
-
- fh = h2o_mem_alloc_shared(NULL, sizeof(*fh), on_dispose_handle);
- fh->logconf = logconf;
- fh->fd = fd;
- return fh;
-}
-
-static void dispose(h2o_logger_t *_self)
-{
- struct st_h2o_access_logger_t *self = (void *)_self;
-
- h2o_mem_release_shared(self->fh);
-}
-
-h2o_logger_t *h2o_access_log_register(h2o_pathconf_t *pathconf, h2o_access_log_filehandle_t *fh)
-{
- struct st_h2o_access_logger_t *self = (void *)h2o_create_logger(pathconf, sizeof(*self));
-
- self->super.dispose = dispose;
- self->super.log_access = log_access;
- self->fh = fh;
- h2o_mem_addref_shared(fh);
-
- return &self->super;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/chunked.c b/web/server/h2o/libh2o/lib/handler/chunked.c
deleted file mode 100644
index b6ad4346b..000000000
--- a/web/server/h2o/libh2o/lib/handler/chunked.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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 <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "h2o.h"
-
-typedef struct st_chunked_encoder_t {
- h2o_ostream_t super;
- char buf[64];
-} chunked_encoder_t;
-
-static void send_chunk(h2o_ostream_t *_self, h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state)
-{
- chunked_encoder_t *self = (void *)_self;
- h2o_iovec_t *outbufs = alloca(sizeof(h2o_iovec_t) * (inbufcnt + 2));
- size_t chunk_size, outbufcnt = 0, i;
-
- /* calc chunk size */
- chunk_size = 0;
- for (i = 0; i != inbufcnt; ++i)
- chunk_size += inbufs[i].len;
- req->bytes_sent += chunk_size;
-
- /* create chunk header and output data */
- if (chunk_size != 0) {
- outbufs[outbufcnt].base = self->buf;
- outbufs[outbufcnt].len = sprintf(self->buf, "%zx\r\n", chunk_size);
- assert(outbufs[outbufcnt].len < sizeof(self->buf));
- outbufcnt++;
- memcpy(outbufs + outbufcnt, inbufs, sizeof(h2o_iovec_t) * inbufcnt);
- outbufcnt += inbufcnt;
- if (state != H2O_SEND_STATE_ERROR) {
- outbufs[outbufcnt].base = "\r\n0\r\n\r\n";
- outbufs[outbufcnt].len = state == H2O_SEND_STATE_FINAL ? 7 : 2;
- outbufcnt++;
- }
- } else if (state == H2O_SEND_STATE_FINAL) {
- outbufs[outbufcnt].base = "0\r\n\r\n";
- outbufs[outbufcnt].len = 5;
- outbufcnt++;
- }
-
- /* if state is error, send a broken chunk to pass the error down to the browser */
- if (state == H2O_SEND_STATE_ERROR) {
- outbufs[outbufcnt].base = "\r\n1\r\n";
- outbufs[outbufcnt].len = 5;
- outbufcnt++;
- }
-
- h2o_ostream_send_next(&self->super, req, outbufs, outbufcnt, state);
-}
-
-static void on_setup_ostream(h2o_filter_t *self, h2o_req_t *req, h2o_ostream_t **slot)
-{
- chunked_encoder_t *encoder;
-
- /* do nothing if not HTTP/1.1 or content-length is known */
- if (req->res.content_length != SIZE_MAX || req->version != 0x101)
- goto Next;
- /* RFC 2616 4.4 states that the following status codes (and response to a HEAD method) should not include message body */
- if ((100 <= req->res.status && req->res.status <= 199) || req->res.status == 204 || req->res.status == 304)
- goto Next;
- else if (h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("HEAD")))
- goto Next;
- /* we cannot handle certain responses (like 101 switching protocols) */
- if (req->res.status != 200) {
- req->http1_is_persistent = 0;
- goto Next;
- }
- /* skip if content-encoding header is being set */
- if (h2o_find_header(&req->res.headers, H2O_TOKEN_TRANSFER_ENCODING, -1) != -1)
- goto Next;
-
- /* set content-encoding header */
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_TRANSFER_ENCODING, NULL, H2O_STRLIT("chunked"));
-
- /* set the flag that tells finalostream that req->bytes_sent is already counted */
- req->bytes_counted_by_ostream = 1;
-
- /* setup filter */
- encoder = (void *)h2o_add_ostream(req, sizeof(chunked_encoder_t), slot);
- encoder->super.do_send = send_chunk;
- slot = &encoder->super.next;
-
-Next:
- h2o_setup_next_ostream(req, slot);
-}
-
-void h2o_chunked_register(h2o_pathconf_t *pathconf)
-{
- h2o_filter_t *self = h2o_create_filter(pathconf, sizeof(*self));
- self->on_setup_ostream = on_setup_ostream;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/compress.c b/web/server/h2o/libh2o/lib/handler/compress.c
deleted file mode 100644
index 615977131..000000000
--- a/web/server/h2o/libh2o/lib/handler/compress.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2015,2016 Justin Zhu, DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <assert.h>
-#include <stdlib.h>
-#include "h2o.h"
-
-#ifndef BUF_SIZE
-#define BUF_SIZE 8192
-#endif
-
-struct st_compress_filter_t {
- h2o_filter_t super;
- h2o_compress_args_t args;
-};
-
-struct st_compress_encoder_t {
- h2o_ostream_t super;
- h2o_compress_context_t *compressor;
-};
-
-static void do_send(h2o_ostream_t *_self, h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state)
-{
- struct st_compress_encoder_t *self = (void *)_self;
- h2o_iovec_t *outbufs;
- size_t outbufcnt;
-
- self->compressor->transform(self->compressor, inbufs, inbufcnt, state, &outbufs, &outbufcnt);
- h2o_ostream_send_next(&self->super, req, outbufs, outbufcnt, state);
-}
-
-static void on_setup_ostream(h2o_filter_t *_self, h2o_req_t *req, h2o_ostream_t **slot)
-{
- struct st_compress_filter_t *self = (void *)_self;
- struct st_compress_encoder_t *encoder;
- int compressible_types;
- h2o_compress_context_t *compressor;
- ssize_t i;
-
- if (req->version < 0x101)
- goto Next;
- if (req->res.status != 200)
- goto Next;
- if (h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("HEAD")))
- goto Next;
-
- switch (req->compress_hint) {
- case H2O_COMPRESS_HINT_DISABLE:
- /* compression was explicitely disabled, skip */
- goto Next;
- case H2O_COMPRESS_HINT_ENABLE:
- /* compression was explicitely enabled */
- break;
- case H2O_COMPRESS_HINT_AUTO:
- default:
- /* no hint from the producer, decide whether to compress based
- on the configuration */
- if (req->res.mime_attr == NULL)
- h2o_req_fill_mime_attributes(req);
- if (!req->res.mime_attr->is_compressible)
- goto Next;
- if (req->res.content_length < self->args.min_size)
- goto Next;
- }
-
- /* skip if failed to gather the list of compressible types */
- if ((compressible_types = h2o_get_compressible_types(&req->headers)) == 0)
- goto Next;
-
- /* skip if content-encoding header is being set (as well as obtain the location of accept-ranges) */
- size_t content_encoding_header_index = -1, accept_ranges_header_index = -1;
- for (i = 0; i != req->res.headers.size; ++i) {
- if (req->res.headers.entries[i].name == &H2O_TOKEN_CONTENT_ENCODING->buf)
- content_encoding_header_index = i;
- else if (req->res.headers.entries[i].name == &H2O_TOKEN_ACCEPT_RANGES->buf)
- accept_ranges_header_index = i;
- else
- continue;
- }
- if (content_encoding_header_index != -1)
- goto Next;
-
-/* open the compressor */
-#if H2O_USE_BROTLI
- if (self->args.brotli.quality != -1 && (compressible_types & H2O_COMPRESSIBLE_BROTLI) != 0) {
- compressor = h2o_compress_brotli_open(&req->pool, self->args.brotli.quality, req->res.content_length);
- } else
-#endif
- if (self->args.gzip.quality != -1 && (compressible_types & H2O_COMPRESSIBLE_GZIP) != 0) {
- compressor = h2o_compress_gzip_open(&req->pool, self->args.gzip.quality);
- } else {
- /* let proxies know that we looked at accept-encoding when deciding not to compress */
- h2o_set_header_token(&req->pool, &req->res.headers, H2O_TOKEN_VARY, H2O_STRLIT("accept-encoding"));
- goto Next;
- }
-
- /* adjust the response headers */
- req->res.content_length = SIZE_MAX;
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_ENCODING, NULL, compressor->name.base, compressor->name.len);
- h2o_set_header_token(&req->pool, &req->res.headers, H2O_TOKEN_VARY, H2O_STRLIT("accept-encoding"));
- if (accept_ranges_header_index != -1) {
- req->res.headers.entries[accept_ranges_header_index].value = h2o_iovec_init(H2O_STRLIT("none"));
- } else {
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_ACCEPT_RANGES, NULL, H2O_STRLIT("none"));
- }
-
- /* setup filter */
- encoder = (void *)h2o_add_ostream(req, sizeof(*encoder), slot);
- encoder->super.do_send = do_send;
- slot = &encoder->super.next;
- encoder->compressor = compressor;
-
- /* adjust preferred chunk size (compress by 8192 bytes) */
- if (req->preferred_chunk_size > BUF_SIZE)
- req->preferred_chunk_size = BUF_SIZE;
-
-Next:
- h2o_setup_next_ostream(req, slot);
-}
-
-void h2o_compress_register(h2o_pathconf_t *pathconf, h2o_compress_args_t *args)
-{
- struct st_compress_filter_t *self = (void *)h2o_create_filter(pathconf, sizeof(*self));
- self->super.on_setup_ostream = on_setup_ostream;
- self->args = *args;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/compress/brotli.cc b/web/server/h2o/libh2o/lib/handler/compress/brotli.cc
deleted file mode 100644
index d4d06e9c4..000000000
--- a/web/server/h2o/libh2o/lib/handler/compress/brotli.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <cassert>
-#include <cstdlib>
-#include <vector>
-#include <zlib.h>
-#include "h2o.h"
-#include "encode.h"
-
-namespace {
- class brotli_context : public h2o_compress_context_t {
- protected:
- brotli::BrotliCompressor *brotli_;
- brotli::BrotliParams params_;
- std::vector<h2o_iovec_t> bufs_; // all bufs_[nnn].base must be free(3)ed
- public:
- brotli_context(int quality, size_t estimated_content_length) : brotli_(NULL) {
- name = h2o_iovec_init(H2O_STRLIT("br"));
- transform = _compress;
- params_.quality = quality;
- if (estimated_content_length != std::numeric_limits<size_t>::max())
- _update_lgwin(params_, estimated_content_length);
- }
- ~brotli_context() {
- _clear_bufs();
- delete brotli_;
- }
- static void dispose(void *_self) {
- brotli_context *self = static_cast<brotli_context *>(_self);
- self->~brotli_context();
- }
- private:
- void _clear_bufs();
- void _emit(bool is_last, bool force_flush);
- void _compress(h2o_iovec_t *inbufs, size_t inbufcnt, int is_final, h2o_iovec_t **outbufs, size_t *outbufcnt);
- static void _compress(h2o_compress_context_t *self, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state,
- h2o_iovec_t **outbufs, size_t *outbufcnt) {
- static_cast<brotli_context*>(self)->_compress(inbufs, inbufcnt, !h2o_send_state_is_in_progress(state), outbufs, outbufcnt);
- }
- static void _update_lgwin(brotli::BrotliParams &params, size_t estimated_content_length);
- };
-}
-
-void brotli_context::_clear_bufs()
-{
- for (std::vector<h2o_iovec_t>::iterator i = bufs_.begin(); i != bufs_.end(); ++i)
- free(i->base);
- bufs_.clear();
-}
-
-void brotli_context::_emit(bool is_last, bool force_flush)
-{
- uint8_t *output;
- size_t out_size;
- bool ret = brotli_->WriteBrotliData(is_last, force_flush, &out_size, &output);
- assert(ret);
- (void)ret;
- if (out_size != 0)
- bufs_.push_back(h2o_strdup(NULL, reinterpret_cast<const char *>(output), out_size));
-}
-
-void brotli_context::_compress(h2o_iovec_t *inbufs, size_t inbufcnt, int is_final, h2o_iovec_t **outbufs, size_t *outbufcnt)
-{
- if (brotli_ == NULL) {
- if (is_final) {
- uint64_t len = 0;
- for (size_t i = 0; i != inbufcnt; ++i)
- len += inbufs[i].len;
- if (len < std::numeric_limits<size_t>::max())
- _update_lgwin(params_, len);
- }
- brotli_ = new brotli::BrotliCompressor(params_);
- }
-
- _clear_bufs();
-
- if (inbufcnt != 0) {
- size_t inbufindex = 0, offset = 0, block_space = brotli_->input_block_size();
- while (inbufindex != inbufcnt) {
- size_t copy_len = std::min(block_space, inbufs[inbufindex].len - offset);
- brotli_->CopyInputToRingBuffer(copy_len, reinterpret_cast<const uint8_t *>(inbufs[inbufindex].base) + offset);
- offset += copy_len;
- if (inbufs[inbufindex].len == offset) {
- if (++inbufindex == inbufcnt)
- break;
- offset = 0;
- }
- if (block_space == 0) {
- _emit(false, false);
- block_space = brotli_->input_block_size();
- }
- }
- _emit(is_final, !is_final);
- } else {
- if (is_final)
- _emit(true, false);
- }
-
- if (is_final) {
- delete brotli_;
- brotli_ = NULL;
- }
-
- *outbufs = &bufs_.front();
- *outbufcnt = bufs_.size();
-}
-
-void brotli_context::_update_lgwin(brotli::BrotliParams &params, size_t estimated_content_length)
-{
- int bits = estimated_content_length > 1 ? sizeof(unsigned long long) * 8 - __builtin_clzll(estimated_content_length - 1) : 1;
- if (bits < params.lgwin)
- params.lgwin = std::max(bits, brotli::kMinWindowBits);
-}
-
-h2o_compress_context_t *h2o_compress_brotli_open(h2o_mem_pool_t *pool, int quality, size_t estimated_content_length)
-{
- brotli_context *ctx = static_cast<brotli_context *>(h2o_mem_alloc_shared(pool, sizeof(*ctx), brotli_context::dispose));
- return new (ctx) brotli_context(quality, estimated_content_length);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/compress/gzip.c b/web/server/h2o/libh2o/lib/handler/compress/gzip.c
deleted file mode 100644
index c12260df3..000000000
--- a/web/server/h2o/libh2o/lib/handler/compress/gzip.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <assert.h>
-#include <stdlib.h>
-#include <zlib.h>
-#include "h2o.h"
-
-#define WINDOW_BITS 31
-#ifndef BUF_SIZE /* is altered by unit test */
-#define BUF_SIZE 8192
-#endif
-
-typedef H2O_VECTOR(h2o_iovec_t) iovec_vector_t;
-
-struct st_gzip_context_t {
- h2o_compress_context_t super;
- z_stream zs;
- int zs_is_open;
- iovec_vector_t bufs;
-};
-
-static void do_compress(h2o_compress_context_t *_self, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state,
- h2o_iovec_t **outbufs, size_t *outbufcnt);
-static void do_decompress(h2o_compress_context_t *_self, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state,
- h2o_iovec_t **outbufs, size_t *outbufcnt);
-
-static void *alloc_cb(void *_unused, unsigned int cnt, unsigned int sz)
-{
- return h2o_mem_alloc(cnt * (size_t)sz);
-}
-
-static void free_cb(void *_unused, void *p)
-{
- free(p);
-}
-
-static void expand_buf(iovec_vector_t *bufs)
-{
- h2o_vector_reserve(NULL, bufs, bufs->size + 1);
- bufs->entries[bufs->size++] = h2o_iovec_init(h2o_mem_alloc(BUF_SIZE), 0);
-}
-
-typedef int (*processor)(z_streamp strm, int flush);
-
-static size_t process_chunk(struct st_gzip_context_t *self, const void *src, size_t len, int flush, size_t bufindex, processor proc)
-{
- int ret;
-
- self->zs.next_in = (void *)src;
- self->zs.avail_in = (unsigned)len;
-
- /* man says: If inflate/deflate returns with avail_out == 0, this function must be called again with the same value of the flush
- * parameter and more output space (updated avail_out), until the flush is complete (function returns with non-zero avail_out).
- */
- do {
- /* expand buffer (note: in case of Z_SYNC_FLUSH we need to supply at least 6 bytes of output buffer) */
- if (self->bufs.entries[bufindex].len + 32 > BUF_SIZE) {
- ++bufindex;
- if (bufindex == self->bufs.size)
- expand_buf(&self->bufs);
- self->bufs.entries[bufindex].len = 0;
- }
- self->zs.next_out = (void *)(self->bufs.entries[bufindex].base + self->bufs.entries[bufindex].len);
- self->zs.avail_out = (unsigned)(BUF_SIZE - self->bufs.entries[bufindex].len);
- ret = proc(&self->zs, flush);
- /* inflate() returns Z_BUF_ERROR if flush is set to Z_FINISH at the middle of the compressed data */
- assert(ret == Z_OK || ret == Z_STREAM_END || ret == Z_BUF_ERROR);
- self->bufs.entries[bufindex].len = BUF_SIZE - self->zs.avail_out;
- } while (self->zs.avail_out == 0 && ret != Z_STREAM_END);
-
- return bufindex;
-}
-
-static void do_process(h2o_compress_context_t *_self, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state,
- h2o_iovec_t **outbufs, size_t *outbufcnt, processor proc)
-{
- struct st_gzip_context_t *self = (void *)_self;
- size_t outbufindex;
- h2o_iovec_t last_buf;
-
- outbufindex = 0;
- self->bufs.entries[0].len = 0;
-
- if (inbufcnt != 0) {
- size_t i;
- for (i = 0; i != inbufcnt - 1; ++i)
- outbufindex = process_chunk(self, inbufs[i].base, inbufs[i].len, Z_NO_FLUSH, outbufindex, proc);
- last_buf = inbufs[i];
- } else {
- last_buf = h2o_iovec_init(NULL, 0);
- }
- outbufindex = process_chunk(self, last_buf.base, last_buf.len, h2o_send_state_is_in_progress(state) ? Z_SYNC_FLUSH : Z_FINISH,
- outbufindex, proc);
-
- *outbufs = self->bufs.entries;
- *outbufcnt = outbufindex + 1;
-
- if (!h2o_send_state_is_in_progress(state)) {
- if (self->super.transform == do_compress) {
- deflateEnd(&self->zs);
- } else {
- inflateEnd(&self->zs);
- }
- self->zs_is_open = 0;
- }
-}
-
-static void do_compress(h2o_compress_context_t *_self, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state,
- h2o_iovec_t **outbufs, size_t *outbufcnt)
-{
- do_process(_self, inbufs, inbufcnt, state, outbufs, outbufcnt, (processor)deflate);
-}
-
-static void do_decompress(h2o_compress_context_t *_self, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state,
- h2o_iovec_t **outbufs, size_t *outbufcnt)
-{
- do_process(_self, inbufs, inbufcnt, state, outbufs, outbufcnt, (processor)inflate);
-}
-
-static void do_free(void *_self)
-{
- struct st_gzip_context_t *self = _self;
- size_t i;
-
- if (self->zs_is_open) {
- if (self->super.transform == do_compress) {
- deflateEnd(&self->zs);
- } else {
- inflateEnd(&self->zs);
- }
- }
-
- for (i = 0; i != self->bufs.size; ++i)
- free(self->bufs.entries[i].base);
- free(self->bufs.entries);
-}
-
-static struct st_gzip_context_t *gzip_open(h2o_mem_pool_t *pool)
-{
- struct st_gzip_context_t *self = h2o_mem_alloc_shared(pool, sizeof(*self), do_free);
-
- self->super.name = h2o_iovec_init(H2O_STRLIT("gzip"));
- self->super.transform = NULL;
- self->zs.zalloc = alloc_cb;
- self->zs.zfree = free_cb;
- self->zs.opaque = NULL;
- self->zs_is_open = 1;
- self->bufs = (iovec_vector_t){NULL};
- expand_buf(&self->bufs);
-
- return self;
-}
-
-h2o_compress_context_t *h2o_compress_gzip_open(h2o_mem_pool_t *pool, int quality)
-{
- struct st_gzip_context_t *self = gzip_open(pool);
- self->super.transform = do_compress;
- /* Z_BEST_SPEED for on-the-fly compression, memlevel set to 8 as suggested by the manual */
- deflateInit2(&self->zs, quality, Z_DEFLATED, WINDOW_BITS, 8, Z_DEFAULT_STRATEGY);
-
- return &self->super;
-}
-
-h2o_compress_context_t *h2o_compress_gunzip_open(h2o_mem_pool_t *pool)
-{
- struct st_gzip_context_t *self = gzip_open(pool);
- self->super.transform = do_decompress;
- inflateInit2(&self->zs, WINDOW_BITS);
-
- return &self->super;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/access_log.c b/web/server/h2o/libh2o/lib/handler/configurator/access_log.c
deleted file mode 100644
index de6380882..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/access_log.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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 "h2o.h"
-#include "h2o/configurator.h"
-
-typedef H2O_VECTOR(h2o_access_log_filehandle_t *) st_h2o_access_log_filehandle_vector_t;
-
-struct st_h2o_access_log_configurator_t {
- h2o_configurator_t super;
- st_h2o_access_log_filehandle_vector_t *handles;
- st_h2o_access_log_filehandle_vector_t _handles_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static int on_config(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_h2o_access_log_configurator_t *self = (void *)cmd->configurator;
- const char *path, *fmt = NULL;
- int escape = H2O_LOGCONF_ESCAPE_APACHE;
- h2o_access_log_filehandle_t *fh;
-
- switch (node->type) {
- case YOML_TYPE_SCALAR:
- path = node->data.scalar;
- break;
- case YOML_TYPE_MAPPING: {
- yoml_t *t;
- /* get path */
- if ((t = yoml_get(node, "path")) == NULL) {
- h2o_configurator_errprintf(cmd, node, "could not find mandatory key `path`");
- return -1;
- }
- if (t->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, t, "`path` must be scalar");
- return -1;
- }
- path = t->data.scalar;
- /* get format */
- if ((t = yoml_get(node, "format")) != NULL) {
- if (t->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, t, "`format` must be a scalar");
- return -1;
- }
- fmt = t->data.scalar;
- }
- /* get escape */
- if ((t = yoml_get(node, "escape")) != NULL) {
- switch (h2o_configurator_get_one_of(cmd, t, "apache,json")) {
- case 0:
- escape = H2O_LOGCONF_ESCAPE_APACHE;
- break;
- case 1:
- escape = H2O_LOGCONF_ESCAPE_JSON;
- break;
- default:
- return -1;
- }
- }
- } break;
- default:
- h2o_configurator_errprintf(cmd, node, "node must be a scalar or a mapping");
- return -1;
- }
-
- if (!ctx->dry_run) {
- if ((fh = h2o_access_log_open_handle(path, fmt, escape)) == NULL)
- return -1;
- h2o_vector_reserve(NULL, self->handles, self->handles->size + 1);
- self->handles->entries[self->handles->size++] = fh;
- }
-
- return 0;
-}
-
-static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_h2o_access_log_configurator_t *self = (void *)_self;
- size_t i;
-
- /* push the stack pointer */
- ++self->handles;
-
- /* link the handles */
- memset(self->handles, 0, sizeof(*self->handles));
- h2o_vector_reserve(NULL, self->handles, self->handles[-1].size + 1);
- for (i = 0; i != self->handles[-1].size; ++i) {
- h2o_access_log_filehandle_t *fh = self->handles[-1].entries[i];
- self->handles[0].entries[self->handles[0].size++] = fh;
- h2o_mem_addref_shared(fh);
- }
-
- return 0;
-}
-
-static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_h2o_access_log_configurator_t *self = (void *)_self;
- size_t i;
-
- /* register all handles, and decref them */
- for (i = 0; i != self->handles->size; ++i) {
- h2o_access_log_filehandle_t *fh = self->handles->entries[i];
- if (ctx->pathconf != NULL)
- h2o_access_log_register(ctx->pathconf, fh);
- h2o_mem_release_shared(fh);
- }
- /* free the vector */
- free(self->handles->entries);
-
- /* pop the stack pointer */
- --self->handles;
-
- return 0;
-}
-
-void h2o_access_log_register_configurator(h2o_globalconf_t *conf)
-{
- struct st_h2o_access_log_configurator_t *self = (void *)h2o_configurator_create(conf, sizeof(*self));
-
- self->super.enter = on_config_enter;
- self->super.exit = on_config_exit;
- self->handles = self->_handles_stack;
-
- h2o_configurator_define_command(&self->super, "access-log", H2O_CONFIGURATOR_FLAG_ALL_LEVELS, on_config);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/compress.c b/web/server/h2o/libh2o/lib/handler/configurator/compress.c
deleted file mode 100644
index c023dd5cf..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/compress.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 "h2o.h"
-#include "h2o/configurator.h"
-
-#define DEFAULT_GZIP_QUALITY 1
-#define DEFAULT_BROTLI_QUALITY 1
-
-struct compress_configurator_t {
- h2o_configurator_t super;
- h2o_compress_args_t *vars, _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static const h2o_compress_args_t all_off = {0, {-1}, {-1}}, all_on = {100, {DEFAULT_GZIP_QUALITY}, {DEFAULT_BROTLI_QUALITY}};
-
-static int on_config_gzip(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct compress_configurator_t *self = (void *)cmd->configurator;
- int mode;
-
- if ((mode = (int)h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
- return -1;
-
- *self->vars = all_off;
- if (mode != 0)
- self->vars->gzip.quality = DEFAULT_GZIP_QUALITY;
-
- return 0;
-}
-
-static int obtain_quality(yoml_t *node, int min_quality, int max_quality, int default_quality, int *slot)
-{
- int tmp;
- if (node->type != YOML_TYPE_SCALAR)
- return -1;
- if (strcasecmp(node->data.scalar, "OFF") == 0) {
- *slot = -1;
- return 0;
- }
- if (strcasecmp(node->data.scalar, "ON") == 0) {
- *slot = default_quality;
- return 0;
- }
- if (sscanf(node->data.scalar, "%d", &tmp) == 1 && (min_quality <= tmp && tmp <= max_quality)) {
- *slot = tmp;
- return 0;
- }
- return -1;
-}
-
-static int on_config_compress_min_size(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct compress_configurator_t *self = (void *)cmd->configurator;
- return h2o_configurator_scanf(cmd, node, "%zu", &self->vars->min_size);
-}
-
-static int on_config_compress(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct compress_configurator_t *self = (void *)cmd->configurator;
- size_t i;
-
- switch (node->type) {
- case YOML_TYPE_SCALAR:
- if (strcasecmp(node->data.scalar, "OFF") == 0) {
- *self->vars = all_off;
- } else if (strcasecmp(node->data.scalar, "ON") == 0) {
- *self->vars = all_on;
- } else {
- h2o_configurator_errprintf(cmd, node, "scalar argument must be either of: `OFF`, `ON`");
- return -1;
- }
- break;
- case YOML_TYPE_SEQUENCE:
- *self->vars = all_off;
- for (i = 0; i != node->data.sequence.size; ++i) {
- yoml_t *element = node->data.sequence.elements[i];
- if (element->type == YOML_TYPE_SCALAR && strcasecmp(element->data.scalar, "gzip") == 0) {
- self->vars->gzip.quality = DEFAULT_GZIP_QUALITY;
- } else if (element->type == YOML_TYPE_SCALAR && strcasecmp(element->data.scalar, "br") == 0) {
- self->vars->brotli.quality = DEFAULT_BROTLI_QUALITY;
- } else {
- h2o_configurator_errprintf(cmd, element, "element of the sequence must be either of: `gzip`, `br`");
- return -1;
- }
- }
- break;
- case YOML_TYPE_MAPPING:
- *self->vars = all_off;
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key;
- yoml_t *value = node->data.mapping.elements[i].value;
- if (key->type == YOML_TYPE_SCALAR && strcasecmp(key->data.scalar, "gzip") == 0) {
- if (obtain_quality(value, 1, 9, DEFAULT_GZIP_QUALITY, &self->vars->gzip.quality) != 0) {
- h2o_configurator_errprintf(
- cmd, value, "value of gzip attribute must be either of `OFF`, `ON` or an integer value between 1 and 9");
- return -1;
- }
- } else if (key->type == YOML_TYPE_SCALAR && strcasecmp(key->data.scalar, "br") == 0) {
- if (obtain_quality(value, 0, 11, DEFAULT_BROTLI_QUALITY, &self->vars->brotli.quality) != 0) {
- h2o_configurator_errprintf(
- cmd, value, "value of br attribute must be either of `OFF`, `ON` or an integer between 0 and 11");
- return -1;
- }
- } else {
- h2o_configurator_errprintf(cmd, key, "key must be either of: `gzip`, `br`");
- return -1;
- }
- }
- break;
- default:
- h2o_fatal("unexpected node type");
- break;
- }
-
- return 0;
-}
-
-static int on_config_enter(h2o_configurator_t *configurator, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct compress_configurator_t *self = (void *)configurator;
-
- ++self->vars;
- self->vars[0] = self->vars[-1];
- return 0;
-}
-
-static int on_config_exit(h2o_configurator_t *configurator, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct compress_configurator_t *self = (void *)configurator;
-
- if (ctx->pathconf != NULL && (self->vars->gzip.quality != -1 || self->vars->brotli.quality != -1))
- h2o_compress_register(ctx->pathconf, self->vars);
-
- --self->vars;
- return 0;
-}
-
-void h2o_compress_register_configurator(h2o_globalconf_t *conf)
-{
- struct compress_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
-
- c->super.enter = on_config_enter;
- c->super.exit = on_config_exit;
- h2o_configurator_define_command(&c->super, "compress", H2O_CONFIGURATOR_FLAG_ALL_LEVELS, on_config_compress);
- h2o_configurator_define_command(&c->super, "compress-minimum-size",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_compress_min_size);
- h2o_configurator_define_command(&c->super, "gzip", H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_gzip);
- c->vars = c->_vars_stack;
- c->vars->gzip.quality = -1;
- c->vars->brotli.quality = -1;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/errordoc.c b/web/server/h2o/libh2o/lib/handler/configurator/errordoc.c
deleted file mode 100644
index ab24923ee..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/errordoc.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2015-2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 "h2o.h"
-#include "h2o/configurator.h"
-
-struct errordoc_configurator_t {
- h2o_configurator_t super;
- h2o_mem_pool_t pool;
- H2O_VECTOR(h2o_errordoc_t) * vars, _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static int scan_and_check_status(h2o_configurator_command_t *cmd, yoml_t *value, int *slot)
-{
- if (value->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, value, "status must be must be either of: scalar, sequence of scalar");
- return -1;
- }
- if (h2o_configurator_scanf(cmd, value, "%d", slot) != 0)
- return -1;
- if (!(400 <= *slot && *slot <= 599)) {
- h2o_configurator_errprintf(cmd, value, "status must be within range of 400 to 599");
- return -1;
- }
- return 0;
-}
-
-static int register_errordoc(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *hash)
-{
- struct errordoc_configurator_t *self = (void *)cmd->configurator;
- int status[200];
- size_t status_len = 0;
- int parsed;
- const char *url = NULL;
- size_t i, j, k;
- yoml_t *key, *value;
-
- for (i = 0; i != hash->data.mapping.size; ++i) {
- key = hash->data.mapping.elements[i].key;
- value = hash->data.mapping.elements[i].value;
- if (key->type != YOML_TYPE_SCALAR)
- goto UnknownKeyError;
- if (strcmp(key->data.scalar, "status") == 0) {
- if (status_len != 0)
- goto KeyAlreadyDefinedError;
-
- if (value->type == YOML_TYPE_SEQUENCE) {
- if (value->data.sequence.size == 0) {
- h2o_configurator_errprintf(cmd, value, "status sequence must not be empty");
- return -1;
- }
- for (j = 0; j != value->data.sequence.size; ++j) {
- if (scan_and_check_status(cmd, value->data.sequence.elements[j], &parsed) != 0)
- return -1;
- /* check the scanned status hasn't already appeared */
- for (k = 0; k != status_len; ++k) {
- if (status[k] == parsed) {
- h2o_configurator_errprintf(cmd, value, "status %d appears multiple times", status[k]);
- return -1;
- }
- }
- status[status_len++] = parsed;
- }
- } else {
- if (scan_and_check_status(cmd, value, &parsed) != 0)
- return -1;
- status[status_len++] = parsed;
- }
-
- } else if (strcmp(key->data.scalar, "url") == 0) {
- if (url != NULL)
- goto KeyAlreadyDefinedError;
- if (value->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, value, "URL must be a scalar");
- return -1;
- }
- url = value->data.scalar;
- } else {
- goto UnknownKeyError;
- }
- }
-
- if (status_len == 0) {
- h2o_configurator_errprintf(cmd, hash, "mandatory key `status` is not defined");
- return -1;
- }
- if (url == NULL) {
- h2o_configurator_errprintf(cmd, hash, "mandatory key `url` is not defined");
- return -1;
- }
-
- h2o_iovec_t _url = h2o_strdup(&self->pool, url, SIZE_MAX);
- for (i = 0; i != status_len; ++i){
- /* register */
- h2o_vector_reserve(&self->pool, self->vars, self->vars->size + 1);
- h2o_errordoc_t *errordoc = self->vars->entries + self->vars->size++;
- errordoc->status = status[i];
- errordoc->url = _url;
- }
-
- return 0;
-
-UnknownKeyError:
- h2o_configurator_errprintf(cmd, key, "key must be either of: `status`, `url`");
- return -1;
-KeyAlreadyDefinedError:
- h2o_configurator_errprintf(cmd, key, "the key cannot be defined more than once");
- return -1;
-}
-
-static int on_config_errordoc(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- switch (node->type) {
- case YOML_TYPE_SEQUENCE: {
- size_t i;
- for (i = 0; i != node->data.sequence.size; ++i) {
- yoml_t *e = node->data.sequence.elements[i];
- if (e->type != YOML_TYPE_MAPPING) {
- h2o_configurator_errprintf(cmd, e, "element must be a mapping");
- return -1;
- }
- if (register_errordoc(cmd, ctx, e) != 0)
- return -1;
- }
- return 0;
- }
- case YOML_TYPE_MAPPING:
- return register_errordoc(cmd, ctx, node);
- default:
- break;
- }
-
- h2o_configurator_errprintf(cmd, node, "argument must be either of: sequence, mapping");
- return -1;
-}
-
-static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct errordoc_configurator_t *self = (void *)_self;
-
- if (self->vars == self->_vars_stack) {
- /* entering global level */
- h2o_mem_init_pool(&self->pool);
- }
-
- /* copy vars */
- memset(&self->vars[1], 0, sizeof(self->vars[1]));
- h2o_vector_reserve(&self->pool, &self->vars[1], self->vars[0].size);
- h2o_memcpy(self->vars[1].entries, self->vars[0].entries, sizeof(self->vars[0].entries[0]) * self->vars[0].size);
- self->vars[1].size = self->vars[0].size;
-
- ++self->vars;
- return 0;
-}
-
-static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct errordoc_configurator_t *self = (void *)_self;
-
- if (ctx->pathconf != NULL && self->vars->size != 0)
- h2o_errordoc_register(ctx->pathconf, self->vars->entries, self->vars->size);
-
- --self->vars;
- if (self->vars == self->_vars_stack) {
- /* exitting global level */
- h2o_mem_clear_pool(&self->pool);
- }
-
- return 0;
-}
-
-void h2o_errordoc_register_configurator(h2o_globalconf_t *conf)
-{
- struct errordoc_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
-
- /* set default vars */
- c->vars = c->_vars_stack;
-
- /* setup handlers */
- c->super.enter = on_config_enter;
- c->super.exit = on_config_exit;
-
- /* reproxy: ON | OFF */
- h2o_configurator_define_command(&c->super, "error-doc", H2O_CONFIGURATOR_FLAG_ALL_LEVELS, on_config_errordoc);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/expires.c b/web/server/h2o/libh2o/lib/handler/configurator/expires.c
deleted file mode 100644
index 01d404dd5..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/expires.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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 <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include "h2o.h"
-#include "h2o/configurator.h"
-
-struct expires_configurator_t {
- h2o_configurator_t super;
- h2o_expires_args_t **args;
- h2o_expires_args_t *_args_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static int on_config_expires(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct expires_configurator_t *self = (void *)cmd->configurator;
- uint64_t value;
- char unit[32];
-
- if (strcasecmp(node->data.scalar, "OFF") == 0) {
- free(*self->args);
- *self->args = NULL;
- } else if (sscanf(node->data.scalar, "%" SCNu64 " %31s", &value, unit) == 2) {
- /* convert value to seconds depending on the unit */
- if (strncasecmp(unit, H2O_STRLIT("second")) == 0) {
- /* ok */
- } else if (strncasecmp(unit, H2O_STRLIT("minute")) == 0) {
- value *= 60;
- } else if (strncasecmp(unit, H2O_STRLIT("hour")) == 0) {
- value *= 60 * 60;
- } else if (strncasecmp(unit, H2O_STRLIT("day")) == 0) {
- value *= 24 * 60 * 60;
- } else if (strncasecmp(unit, H2O_STRLIT("month")) == 0) {
- value *= 30 * 24 * 60 * 60;
- } else if (strncasecmp(unit, H2O_STRLIT("year")) == 0) {
- value *= 365 * 30 * 24 * 60 * 60;
- } else {
- /* TODO add support for H2O_EXPIRES_MODE_MAX_ABSOLUTE that sets the Expires header? */
- h2o_configurator_errprintf(cmd, node, "unknown unit:`%s` (see --help)", unit);
- return -1;
- }
- /* save the value */
- if (*self->args == NULL)
- *self->args = h2o_mem_alloc(sizeof(**self->args));
- (*self->args)->mode = H2O_EXPIRES_MODE_MAX_AGE;
- (*self->args)->data.max_age = value;
- } else {
- h2o_configurator_errprintf(cmd, node,
- "failed to parse the value, should be in form of: `<number> <unit>` or `OFF` (see --help)");
- return -1;
- }
-
- return 0;
-}
-
-static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct expires_configurator_t *self = (void *)_self;
-
- if (self->args[0] != NULL) {
- /* duplicate */
- assert(self->args[0]->mode == H2O_EXPIRES_MODE_MAX_AGE);
- self->args[1] = h2o_mem_alloc(sizeof(**self->args));
- *self->args[1] = *self->args[0];
- } else {
- self->args[1] = NULL;
- }
- ++self->args;
- return 0;
-}
-
-static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct expires_configurator_t *self = (void *)_self;
-
- if (*self->args != NULL) {
- /* setup */
- if (ctx->pathconf != NULL) {
- h2o_expires_register(ctx->pathconf, *self->args);
- }
- /* destruct */
- assert((*self->args)->mode == H2O_EXPIRES_MODE_MAX_AGE);
- free(*self->args);
- *self->args = NULL;
- }
-
- --self->args;
- return 0;
-}
-
-void h2o_expires_register_configurator(h2o_globalconf_t *conf)
-{
- struct expires_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
-
- /* set default vars */
- c->args = c->_args_stack;
-
- /* setup handlers */
- c->super.enter = on_config_enter;
- c->super.exit = on_config_exit;
- h2o_configurator_define_command(&c->super, "expires", H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_expires);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/fastcgi.c b/web/server/h2o/libh2o/lib/handler/configurator/fastcgi.c
deleted file mode 100644
index bf89b7b26..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/fastcgi.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd. Kazuho Oku
- *
- * 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 <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <pwd.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-#include "h2o.h"
-#include "h2o/configurator.h"
-#include "h2o/serverutil.h"
-
-struct fastcgi_configurator_t {
- h2o_configurator_t super;
- h2o_fastcgi_config_vars_t *vars;
- h2o_fastcgi_config_vars_t _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static int on_config_timeout_io(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct fastcgi_configurator_t *self = (void *)cmd->configurator;
- return h2o_configurator_scanf(cmd, node, "%" SCNu64, &self->vars->io_timeout);
-}
-
-static int on_config_timeout_keepalive(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct fastcgi_configurator_t *self = (void *)cmd->configurator;
- return h2o_configurator_scanf(cmd, node, "%" SCNu64, &self->vars->keepalive_timeout);
-}
-
-static int on_config_document_root(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct fastcgi_configurator_t *self = (void *)cmd->configurator;
-
- if (node->data.scalar[0] == '\0') {
- /* unset */
- self->vars->document_root = h2o_iovec_init(NULL, 0);
- } else if (node->data.scalar[0] == '/') {
- /* set */
- self->vars->document_root = h2o_iovec_init(node->data.scalar, strlen(node->data.scalar));
- } else {
- h2o_configurator_errprintf(cmd, node, "value does not start from `/`");
- return -1;
- }
- return 0;
-}
-
-static int on_config_send_delegated_uri(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct fastcgi_configurator_t *self = (void *)cmd->configurator;
- ssize_t v;
-
- if ((v = h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
- return -1;
- self->vars->send_delegated_uri = (int)v;
- return 0;
-}
-
-static int on_config_connect(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct fastcgi_configurator_t *self = (void *)cmd->configurator;
- const char *hostname = "127.0.0.1", *servname = NULL, *type = "tcp";
-
- /* fetch servname (and hostname) */
- switch (node->type) {
- case YOML_TYPE_SCALAR:
- servname = node->data.scalar;
- break;
- case YOML_TYPE_MAPPING: {
- yoml_t *t;
- if ((t = yoml_get(node, "host")) != NULL) {
- if (t->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, t, "`host` is not a string");
- return -1;
- }
- hostname = t->data.scalar;
- }
- if ((t = yoml_get(node, "port")) == NULL) {
- h2o_configurator_errprintf(cmd, node, "cannot find mandatory property `port`");
- return -1;
- }
- if (t->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, node, "`port` is not a string");
- return -1;
- }
- servname = t->data.scalar;
- if ((t = yoml_get(node, "type")) != NULL) {
- if (t->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, t, "`type` is not a string");
- return -1;
- }
- type = t->data.scalar;
- }
- } break;
- default:
- h2o_configurator_errprintf(cmd, node,
- "value must be a string or a mapping (with keys: `port` and optionally `host` and `type`)");
- return -1;
- }
-
- if (strcmp(type, "unix") == 0) {
- /* unix socket */
- struct sockaddr_un sa;
- memset(&sa, 0, sizeof(sa));
- if (strlen(servname) >= sizeof(sa.sun_path)) {
- h2o_configurator_errprintf(cmd, node, "path:%s is too long as a unix socket name", servname);
- return -1;
- }
- sa.sun_family = AF_UNIX;
- strcpy(sa.sun_path, servname);
- h2o_fastcgi_register_by_address(ctx->pathconf, (void *)&sa, sizeof(sa), self->vars);
- } else if (strcmp(type, "tcp") == 0) {
- /* tcp socket */
- uint16_t port;
- if (sscanf(servname, "%" SCNu16, &port) != 1) {
- h2o_configurator_errprintf(cmd, node, "invalid port number:%s", servname);
- return -1;
- }
- h2o_fastcgi_register_by_hostport(ctx->pathconf, hostname, port, self->vars);
- } else {
- h2o_configurator_errprintf(cmd, node, "unknown listen type: %s", type);
- return -1;
- }
-
- return 0;
-}
-
-static int create_spawnproc(h2o_configurator_command_t *cmd, yoml_t *node, const char *dirname, char *const *argv,
- struct sockaddr_un *sa, struct passwd *pw)
-{
- int ret, listen_fd = -1, pipe_fds[2] = {-1, -1};
-
- /* build socket path */
- sa->sun_family = AF_UNIX;
- ret = snprintf(sa->sun_path, sizeof(sa->sun_path), "%s/_", dirname);
- if (ret < 0 || ret >= sizeof(sa->sun_path)) {
- h2o_configurator_errprintf(cmd, node, "unix socket path too long: %s", dirname);
- goto Error;
- }
-
- /* create socket */
- if ((listen_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
- h2o_configurator_errprintf(cmd, node, "socket(2) failed: %s", strerror(errno));
- goto Error;
- }
- if (bind(listen_fd, (void *)sa, sizeof(*sa)) != 0) {
- h2o_configurator_errprintf(cmd, node, "bind(2) failed: %s", strerror(errno));
- goto Error;
- }
- if (listen(listen_fd, H2O_SOMAXCONN) != 0) {
- h2o_configurator_errprintf(cmd, node, "listen(2) failed: %s", strerror(errno));
- goto Error;
- }
- /* change ownership of socket */
- if (pw != NULL && chown(sa->sun_path, pw->pw_uid, pw->pw_gid) != 0) {
- h2o_configurator_errprintf(cmd, node, "chown(2) failed to change ownership of socket:%s:%s", sa->sun_path, strerror(errno));
- goto Error;
- }
-
- /* create pipe which is used to notify the termination of the server */
- if (pipe(pipe_fds) != 0) {
- h2o_configurator_errprintf(cmd, node, "pipe(2) failed: %s", strerror(errno));
- pipe_fds[0] = -1;
- pipe_fds[1] = -1;
- goto Error;
- }
- if (fcntl(pipe_fds[1], F_SETFD, FD_CLOEXEC) < 0)
- goto Error;
-
- /* spawn */
- int mapped_fds[] = {listen_fd, 0, /* listen_fd to 0 */
- pipe_fds[0], 5, /* pipe_fds[0] to 5 */
- -1};
- pid_t pid = h2o_spawnp(argv[0], argv, mapped_fds, 0);
- if (pid == -1) {
- fprintf(stderr, "[lib/handler/fastcgi.c] failed to launch helper program %s:%s\n", argv[0], strerror(errno));
- goto Error;
- }
-
- close(listen_fd);
- listen_fd = -1;
- close(pipe_fds[0]);
- pipe_fds[0] = -1;
-
- return pipe_fds[1];
-
-Error:
- if (pipe_fds[0] != -1)
- close(pipe_fds[0]);
- if (pipe_fds[1])
- close(pipe_fds[1]);
- if (listen_fd != -1)
- close(listen_fd);
- unlink(sa->sun_path);
- return -1;
-}
-
-static void spawnproc_on_dispose(h2o_fastcgi_handler_t *handler, void *data)
-{
- int pipe_fd = (int)((char *)data - (char *)NULL);
- close(pipe_fd);
-}
-
-static int on_config_spawn(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct fastcgi_configurator_t *self = (void *)cmd->configurator;
- char *spawn_user = NULL, *spawn_cmd;
- char *kill_on_close_cmd_path = NULL, *setuidgid_cmd_path = NULL;
- char dirname[] = "/tmp/h2o.fcgisock.XXXXXX";
- char *argv[10];
- int spawner_fd;
- struct sockaddr_un sa;
- h2o_fastcgi_config_vars_t config_vars;
- int ret = -1;
- struct passwd h2o_user_pwbuf, *h2o_user_pw;
- char h2o_user_buf[65536];
-
- memset(&sa, 0, sizeof(sa));
-
- switch (node->type) {
- case YOML_TYPE_SCALAR:
- spawn_user = ctx->globalconf->user;
- spawn_cmd = node->data.scalar;
- break;
- case YOML_TYPE_MAPPING: {
- yoml_t *t;
- if ((t = yoml_get(node, "command")) == NULL) {
- h2o_configurator_errprintf(cmd, node, "mandatory attribute `command` does not exist");
- return -1;
- }
- if (t->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, node, "attribute `command` must be scalar");
- return -1;
- }
- spawn_cmd = t->data.scalar;
- spawn_user = ctx->globalconf->user;
- if ((t = yoml_get(node, "user")) != NULL) {
- if (t->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, node, "attribute `user` must be scalar");
- return -1;
- }
- spawn_user = t->data.scalar;
- }
- } break;
- default:
- h2o_configurator_errprintf(cmd, node, "argument must be scalar or mapping");
- return -1;
- }
-
- /* obtain uid & gid of the client that connects to the FastCGI daemon (i.e. H2O after dropping privileges) */
- if (ctx->globalconf->user != NULL) {
- /* change ownership of temporary directory */
- if (getpwnam_r(ctx->globalconf->user, &h2o_user_pwbuf, h2o_user_buf, sizeof(h2o_user_buf), &h2o_user_pw) != 0 ||
- h2o_user_pw == NULL) {
- h2o_configurator_errprintf(cmd, node, "getpwnam_r(3) failed to obtain uid of user:%s", ctx->globalconf->user);
- goto Exit;
- }
- } else {
- h2o_user_pw = NULL;
- }
-
- { /* build args */
- size_t i = 0;
- argv[i++] = kill_on_close_cmd_path = h2o_configurator_get_cmd_path("share/h2o/kill-on-close");
- argv[i++] = "--rm";
- argv[i++] = dirname;
- argv[i++] = "--";
- if (spawn_user != NULL) {
- argv[i++] = setuidgid_cmd_path = h2o_configurator_get_cmd_path("share/h2o/setuidgid");
- argv[i++] = spawn_user;
- }
- argv[i++] = "/bin/sh";
- argv[i++] = "-c";
- argv[i++] = spawn_cmd;
- argv[i++] = NULL;
- assert(i <= sizeof(argv) / sizeof(argv[0]));
- }
-
- if (ctx->dry_run) {
- dirname[0] = '\0';
- spawner_fd = -1;
- sa.sun_family = AF_UNIX;
- strcpy(sa.sun_path, "/dry-run.nonexistent");
- } else {
- /* create temporary directory */
- if (mkdtemp(dirname) == NULL) {
- h2o_configurator_errprintf(cmd, node, "mkdtemp(3) failed to create temporary directory:%s:%s", dirname,
- strerror(errno));
- dirname[0] = '\0';
- goto Exit;
- }
- /* change ownership of temporary directory */
- if (h2o_user_pw != NULL && chown(dirname, h2o_user_pw->pw_uid, h2o_user_pw->pw_gid) != 0) {
- h2o_configurator_errprintf(cmd, node, "chown(2) failed to change ownership of temporary directory:%s:%s", dirname,
- strerror(errno));
- goto Exit;
- }
- /* launch spawnfcgi command */
- if ((spawner_fd = create_spawnproc(cmd, node, dirname, argv, &sa, h2o_user_pw)) == -1) {
- goto Exit;
- }
- }
-
- config_vars = *self->vars;
- config_vars.callbacks.dispose = spawnproc_on_dispose;
- config_vars.callbacks.data = (char *)NULL + spawner_fd;
- h2o_fastcgi_register_by_address(ctx->pathconf, (void *)&sa, sizeof(sa), &config_vars);
-
- ret = 0;
-Exit:
- if (dirname[0] != '\0')
- unlink(dirname);
- free(kill_on_close_cmd_path);
- free(setuidgid_cmd_path);
- return ret;
-}
-
-static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct fastcgi_configurator_t *self = (void *)_self;
-
- memcpy(self->vars + 1, self->vars, sizeof(*self->vars));
- ++self->vars;
- return 0;
-}
-
-static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct fastcgi_configurator_t *self = (void *)_self;
-
- --self->vars;
- return 0;
-}
-
-void h2o_fastcgi_register_configurator(h2o_globalconf_t *conf)
-{
- struct fastcgi_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
-
- /* set default vars */
- c->vars = c->_vars_stack;
- c->vars->io_timeout = H2O_DEFAULT_FASTCGI_IO_TIMEOUT;
- c->vars->keepalive_timeout = 0;
-
- /* setup handlers */
- c->super.enter = on_config_enter;
- c->super.exit = on_config_exit;
-
- h2o_configurator_define_command(&c->super, "fastcgi.connect",
- H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_EXTENSION | H2O_CONFIGURATOR_FLAG_DEFERRED,
- on_config_connect);
- h2o_configurator_define_command(&c->super, "fastcgi.spawn",
- H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_EXTENSION | H2O_CONFIGURATOR_FLAG_DEFERRED,
- on_config_spawn);
- h2o_configurator_define_command(&c->super, "fastcgi.timeout.io",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_timeout_io);
- h2o_configurator_define_command(&c->super, "fastcgi.timeout.keepalive",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_timeout_keepalive);
- h2o_configurator_define_command(&c->super, "fastcgi.document_root",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_document_root);
- h2o_configurator_define_command(&c->super, "fastcgi.send-delegated-uri",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_send_delegated_uri);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/file.c b/web/server/h2o/libh2o/lib/handler/configurator/file.c
deleted file mode 100644
index c1c779c68..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/file.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * 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 "h2o.h"
-#include "h2o/configurator.h"
-
-struct st_h2o_file_config_vars_t {
- const char **index_files;
- int flags;
-};
-
-struct st_h2o_file_configurator_t {
- h2o_configurator_t super;
- struct st_h2o_file_config_vars_t *vars;
- struct st_h2o_file_config_vars_t _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static int on_config_dir(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
-
- h2o_file_register(ctx->pathconf, node->data.scalar, self->vars->index_files, *ctx->mimemap, self->vars->flags);
- return 0;
-}
-
-static int on_config_file(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
- h2o_mimemap_type_t *mime_type =
- h2o_mimemap_get_type_by_extension(*ctx->mimemap, h2o_get_filext(node->data.scalar, strlen(node->data.scalar)));
- h2o_file_register_file(ctx->pathconf, node->data.scalar, mime_type, self->vars->flags);
- return 0;
-}
-
-static int on_config_index(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
- size_t i;
-
- free(self->vars->index_files);
- self->vars->index_files = h2o_mem_alloc(sizeof(self->vars->index_files[0]) * (node->data.sequence.size + 1));
- for (i = 0; i != node->data.sequence.size; ++i) {
- yoml_t *element = node->data.sequence.elements[i];
- if (element->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, element, "argument must be a sequence of scalars");
- return -1;
- }
- self->vars->index_files[i] = element->data.scalar;
- }
- self->vars->index_files[i] = NULL;
-
- return 0;
-}
-
-static int on_config_etag(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
-
- switch (h2o_configurator_get_one_of(cmd, node, "OFF,ON")) {
- case 0: /* off */
- self->vars->flags |= H2O_FILE_FLAG_NO_ETAG;
- break;
- case 1: /* on */
- self->vars->flags &= ~H2O_FILE_FLAG_NO_ETAG;
- break;
- default: /* error */
- return -1;
- }
-
- return 0;
-}
-
-static int on_config_send_compressed(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
-
- switch (h2o_configurator_get_one_of(cmd, node, "OFF,ON,gunzip")) {
- case 0: /* off */
- self->vars->flags &= ~H2O_FILE_FLAG_SEND_COMPRESSED;
- break;
- case 1: /* on */
- self->vars->flags |= H2O_FILE_FLAG_SEND_COMPRESSED;
- break;
- case 2: /* gunzip */
- self->vars->flags |= (H2O_FILE_FLAG_SEND_COMPRESSED | H2O_FILE_FLAG_GUNZIP);
- break;
- default: /* error */
- return -1;
- }
-
- return 0;
-}
-
-static int on_config_dir_listing(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_h2o_file_configurator_t *self = (void *)cmd->configurator;
-
- switch (h2o_configurator_get_one_of(cmd, node, "OFF,ON")) {
- case 0: /* off */
- self->vars->flags &= ~H2O_FILE_FLAG_DIR_LISTING;
- break;
- case 1: /* on */
- self->vars->flags |= H2O_FILE_FLAG_DIR_LISTING;
- break;
- default: /* error */
- return -1;
- }
-
- return 0;
-}
-
-static const char **dup_strlist(const char **s)
-{
- size_t i;
- const char **ret;
-
- for (i = 0; s[i] != NULL; ++i)
- ;
- ret = h2o_mem_alloc(sizeof(*ret) * (i + 1));
- for (i = 0; s[i] != NULL; ++i)
- ret[i] = s[i];
- ret[i] = NULL;
-
- return ret;
-}
-
-static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_h2o_file_configurator_t *self = (void *)_self;
- ++self->vars;
- self->vars[0].index_files = dup_strlist(self->vars[-1].index_files);
- self->vars[0].flags = self->vars[-1].flags;
- return 0;
-}
-
-static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_h2o_file_configurator_t *self = (void *)_self;
- free(self->vars->index_files);
- --self->vars;
- return 0;
-}
-
-void h2o_file_register_configurator(h2o_globalconf_t *globalconf)
-{
- struct st_h2o_file_configurator_t *self = (void *)h2o_configurator_create(globalconf, sizeof(*self));
-
- self->super.enter = on_config_enter;
- self->super.exit = on_config_exit;
- self->vars = self->_vars_stack;
- self->vars->index_files = h2o_file_default_index_files;
-
- h2o_configurator_define_command(&self->super, "file.dir", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR |
- H2O_CONFIGURATOR_FLAG_DEFERRED,
- on_config_dir);
- h2o_configurator_define_command(&self->super, "file.file", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR |
- H2O_CONFIGURATOR_FLAG_DEFERRED,
- on_config_file);
- h2o_configurator_define_command(&self->super, "file.index",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_SEQUENCE,
- on_config_index);
- h2o_configurator_define_command(&self->super, "file.etag",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_etag);
- h2o_configurator_define_command(&self->super, "file.send-compressed",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_send_compressed);
- h2o_configurator_define_command(&self->super, "file.send-gzip",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_send_compressed);
- h2o_configurator_define_command(&self->super, "file.dirlisting",
- (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_dir_listing);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/headers.c b/web/server/h2o/libh2o/lib/handler/configurator/headers.c
deleted file mode 100644
index 68536c052..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/headers.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <string.h>
-#include "h2o.h"
-#include "h2o/configurator.h"
-
-struct headers_configurator_t {
- h2o_configurator_t super;
- h2o_headers_command_t **cmds, *_cmd_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct headers_configurator_t *self = (void *)_self;
-
- self->cmds[1] = self->cmds[0];
- if (self->cmds[1] != NULL)
- h2o_mem_addref_shared(self->cmds[1]);
-
- ++self->cmds;
- return 0;
-}
-
-static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct headers_configurator_t *self = (void *)_self;
-
- if (ctx->pathconf != NULL && *self->cmds != NULL) {
- if (*self->cmds != NULL)
- h2o_mem_addref_shared(*self->cmds);
- h2o_headers_register(ctx->pathconf, *self->cmds);
- }
-
- if (*self->cmds != NULL)
- h2o_mem_release_shared(*self->cmds);
- --self->cmds;
- return 0;
-}
-
-static h2o_headers_command_t **get_headers_commands(h2o_configurator_t *_self)
-{
- struct headers_configurator_t *self = (void *)_self;
- return self->cmds;
-}
-
-void h2o_headers_register_configurator(h2o_globalconf_t *conf)
-{
- struct headers_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
-
- c->super.enter = on_config_enter;
- c->super.exit = on_config_exit;
-
- h2o_configurator_define_headers_commands(conf, &c->super, "header", get_headers_commands);
- c->cmds = c->_cmd_stack;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/headers_util.c b/web/server/h2o/libh2o/lib/handler/configurator/headers_util.c
deleted file mode 100644
index c05b9b7c2..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/headers_util.c
+++ /dev/null
@@ -1,143 +0,0 @@
-#include "h2o.h"
-#include "h2o/configurator.h"
-
-struct headers_util_configurator_t {
- h2o_configurator_t super;
- h2o_configurator_t *child;
- h2o_configurator_get_headers_commands_cb get_commands;
-};
-
-static int extract_name(const char *src, size_t len, h2o_iovec_t **_name)
-{
- h2o_iovec_t name;
- const h2o_token_t *name_token;
-
- name = h2o_str_stripws(src, len);
- if (name.len == 0)
- return -1;
-
- name = h2o_strdup(NULL, name.base, name.len);
- h2o_strtolower(name.base, name.len);
-
- if ((name_token = h2o_lookup_token(name.base, name.len)) != NULL) {
- *_name = (h2o_iovec_t *)&name_token->buf;
- free(name.base);
- } else {
- *_name = h2o_mem_alloc(sizeof(**_name));
- **_name = name;
- }
-
- return 0;
-}
-
-static int extract_name_value(const char *src, h2o_iovec_t **name, h2o_iovec_t *value)
-{
- const char *colon = strchr(src, ':');
-
- if (colon == NULL)
- return -1;
-
- if (extract_name(src, colon - src, name) != 0)
- return -1;
- *value = h2o_str_stripws(colon + 1, strlen(colon + 1));
- *value = h2o_strdup(NULL, value->base, value->len);
-
- return 0;
-}
-
-static int add_cmd(h2o_configurator_command_t *cmd, yoml_t *node, int cmd_id, h2o_iovec_t *name, h2o_iovec_t value,
- h2o_headers_command_t **cmds)
-{
- if (h2o_iovec_is_token(name)) {
- const h2o_token_t *token = (void *)name;
- if (h2o_headers_is_prohibited_name(token)) {
- h2o_configurator_errprintf(cmd, node, "the named header cannot be rewritten");
- return -1;
- }
- }
-
- h2o_headers_append_command(cmds, cmd_id, name, value);
- return 0;
-}
-
-static int on_config_header_2arg(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, int cmd_id, yoml_t *node,
- h2o_headers_command_t **headers_cmds)
-{
- h2o_iovec_t *name, value;
-
- if (extract_name_value(node->data.scalar, &name, &value) != 0) {
- h2o_configurator_errprintf(cmd, node, "failed to parse the value; should be in form of `name: value`");
- return -1;
- }
- if (add_cmd(cmd, node, cmd_id, name, value, headers_cmds) != 0) {
- if (!h2o_iovec_is_token(name))
- free(name->base);
- free(value.base);
- return -1;
- }
- return 0;
-}
-
-static int on_config_header_unset(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- h2o_iovec_t *name;
- struct headers_util_configurator_t *self = (void *)cmd->configurator;
-
- if (extract_name(node->data.scalar, strlen(node->data.scalar), &name) != 0) {
- h2o_configurator_errprintf(cmd, node, "invalid header name");
- return -1;
- }
- if (add_cmd(cmd, node, H2O_HEADERS_CMD_UNSET, name, (h2o_iovec_t){NULL}, self->get_commands(self->child)) != 0) {
- if (!h2o_iovec_is_token(name))
- free(name->base);
- return -1;
- }
- return 0;
-}
-
-#define DEFINE_2ARG(fn, cmd_id) \
- static int fn(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node) \
- { \
- struct headers_util_configurator_t *self = (void *)cmd->configurator; \
- return on_config_header_2arg(cmd, ctx, cmd_id, node, self->get_commands(self->child)); \
- }
-
-DEFINE_2ARG(on_config_header_add, H2O_HEADERS_CMD_ADD)
-DEFINE_2ARG(on_config_header_append, H2O_HEADERS_CMD_APPEND)
-DEFINE_2ARG(on_config_header_merge, H2O_HEADERS_CMD_MERGE)
-DEFINE_2ARG(on_config_header_set, H2O_HEADERS_CMD_SET)
-DEFINE_2ARG(on_config_header_setifempty, H2O_HEADERS_CMD_SETIFEMPTY)
-
-#undef DEFINE_2ARG
-
-void h2o_configurator_define_headers_commands(h2o_globalconf_t *global_conf, h2o_configurator_t *conf, const char *prefix,
- h2o_configurator_get_headers_commands_cb get_commands)
-{
- struct headers_util_configurator_t *c = (void *)h2o_configurator_create(global_conf, sizeof(*c));
- c->child = conf;
- c->get_commands = get_commands;
- size_t prefix_len = strlen(prefix);
-
-#define DEFINE_CMD_NAME(name, suffix) \
- char *name = h2o_mem_alloc(prefix_len + sizeof(suffix)); \
- memcpy(name, prefix, prefix_len); \
- memcpy(name + prefix_len, suffix, sizeof(suffix))
-
- DEFINE_CMD_NAME(add_directive, ".add");
- DEFINE_CMD_NAME(append_directive, ".append");
- DEFINE_CMD_NAME(merge_directive, ".merge");
- DEFINE_CMD_NAME(set_directive, ".set");
- DEFINE_CMD_NAME(setifempty_directive, ".setifempty");
- DEFINE_CMD_NAME(unset_directive, ".unset");
-#undef DEFINE_CMD_NAME
-
-#define DEFINE_CMD(name, cb) \
- h2o_configurator_define_command(&c->super, name, H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, cb)
- DEFINE_CMD(add_directive, on_config_header_add);
- DEFINE_CMD(append_directive, on_config_header_append);
- DEFINE_CMD(merge_directive, on_config_header_merge);
- DEFINE_CMD(set_directive, on_config_header_set);
- DEFINE_CMD(setifempty_directive, on_config_header_setifempty);
- DEFINE_CMD(unset_directive, on_config_header_unset);
-#undef DEFINE_CMD
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/http2_debug_state.c b/web/server/h2o/libh2o/lib/handler/configurator/http2_debug_state.c
deleted file mode 100644
index 419da9de8..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/http2_debug_state.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2016 DeNA Co., Ltd., Ichito Nagata
- *
- * 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 "h2o.h"
-#include "h2o/configurator.h"
-
-static int on_config_debug_state(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- switch (h2o_configurator_get_one_of(cmd, node, "minimum,hpack")) {
- case 0: /* minimum */
- h2o_http2_debug_state_register(ctx->hostconf, 0);
- return 0;
- case 1: /* with hpack state*/
- h2o_http2_debug_state_register(ctx->hostconf, 1);
- return 0;
- default: /* error */
- return -1;
- }
-}
-
-void h2o_http2_debug_state_register_configurator(h2o_globalconf_t *conf)
-{
- struct st_h2o_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
-
- h2o_configurator_define_command(c, "http2-debug-state", H2O_CONFIGURATOR_FLAG_HOST | H2O_CONFIGURATOR_FLAG_DEFERRED |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_debug_state);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/mruby.c b/web/server/h2o/libh2o/lib/handler/configurator/mruby.c
deleted file mode 100644
index 1cef8f499..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/mruby.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku, Ryosuke Matsumoto
- *
- * 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 <errno.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "h2o.h"
-#include "h2o/configurator.h"
-#include "h2o/mruby_.h"
-
-struct mruby_configurator_t {
- h2o_configurator_t super;
- h2o_mruby_config_vars_t *vars;
- h2o_mruby_config_vars_t _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
- mrb_state *mrb; /* will be lazily initialized */
-};
-
-static int compile_test(mrb_state *mrb, h2o_mruby_config_vars_t *config, char *errbuf)
-{
- mrb_value result = h2o_mruby_compile_code(mrb, config, errbuf);
- int ok = !mrb_nil_p(result);
- return ok;
-}
-
-static mrb_state *get_mrb(struct mruby_configurator_t *self)
-{
- if (self->mrb == NULL) {
- self->mrb = mrb_open();
- if (self->mrb == NULL) {
- fprintf(stderr, "%s: no memory\n", H2O_MRUBY_MODULE_NAME);
- abort();
- }
- h2o_mruby_setup_globals(self->mrb);
- }
- return self->mrb;
-}
-
-static int on_config_mruby_handler(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct mruby_configurator_t *self = (void *)cmd->configurator;
-
- /* set source */
- self->vars->source = h2o_strdup(NULL, node->data.scalar, SIZE_MAX);
- self->vars->path = node->filename;
- self->vars->lineno = (int)node->line + 1;
-
- /* check if there is any error in source */
- char errbuf[1024];
- if (!compile_test(get_mrb(self), self->vars, errbuf)) {
- h2o_configurator_errprintf(cmd, node, "ruby compile error:%s", errbuf);
- return -1;
- }
-
- /* register */
- h2o_mruby_register(ctx->pathconf, self->vars);
-
- return 0;
-}
-
-static int on_config_mruby_handler_file(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct mruby_configurator_t *self = (void *)cmd->configurator;
- FILE *fp = NULL;
- h2o_iovec_t buf = {NULL};
- int ret = -1;
-
- /* open and read file */
- if ((fp = fopen(node->data.scalar, "rt")) == NULL) {
- h2o_configurator_errprintf(cmd, node, "failed to open file: %s:%s", node->data.scalar, strerror(errno));
- goto Exit;
- }
- while (!feof(fp)) {
- buf.base = h2o_mem_realloc(buf.base, buf.len + 65536);
- buf.len += fread(buf.base + buf.len, 1, 65536, fp);
- if (ferror(fp)) {
- h2o_configurator_errprintf(cmd, node, "I/O error occurred while reading file:%s:%s", node->data.scalar,
- strerror(errno));
- goto Exit;
- }
- }
-
- /* set source */
- self->vars->source = buf;
- buf.base = NULL;
- self->vars->path = node->data.scalar; /* the value is retained until the end of the configuration phase */
- self->vars->lineno = 0;
-
- /* check if there is any error in source */
- char errbuf[1024];
- if (!compile_test(get_mrb(self), self->vars, errbuf)) {
- h2o_configurator_errprintf(cmd, node, "failed to compile file:%s:%s", node->data.scalar, errbuf);
- goto Exit;
- }
-
- /* register */
- h2o_mruby_register(ctx->pathconf, self->vars);
-
- ret = 0;
-
-Exit:
- if (fp != NULL)
- fclose(fp);
- if (buf.base != NULL)
- free(buf.base);
- return ret;
-}
-
-static int on_config_mruby_handler_path(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- h2o_configurator_errprintf(cmd, node, "the command has been removed; see https://github.com/h2o/h2o/pull/467");
- return -1;
-}
-
-static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct mruby_configurator_t *self = (void *)_self;
-
- memcpy(self->vars + 1, self->vars, sizeof(*self->vars));
- ++self->vars;
- return 0;
-}
-
-static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct mruby_configurator_t *self = (void *)_self;
-
- /* free if the to-be-exitted frame level contains a different source */
- if (self->vars[-1].source.base != self->vars[0].source.base)
- free(self->vars->source.base);
-
- --self->vars;
-
- /* release mrb only when global configuration exited */
- if (self->mrb != NULL && ctx->parent == NULL) {
- mrb_close(self->mrb);
- self->mrb = NULL;
- }
-
- return 0;
-}
-
-void h2o_mruby_register_configurator(h2o_globalconf_t *conf)
-{
- struct mruby_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
-
- c->vars = c->_vars_stack;
- c->super.enter = on_config_enter;
- c->super.exit = on_config_exit;
-
- h2o_configurator_define_command(&c->super, "mruby.handler", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_DEFERRED |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_mruby_handler);
- h2o_configurator_define_command(&c->super, "mruby.handler-file", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_DEFERRED |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_mruby_handler_file);
- h2o_configurator_define_command(&c->super, "mruby.handler_path", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_DEFERRED,
- on_config_mruby_handler_path);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/proxy.c b/web/server/h2o/libh2o/lib/handler/configurator/proxy.c
deleted file mode 100644
index cfc9cbf40..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/proxy.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * 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 <inttypes.h>
-#include <errno.h>
-#include <stdio.h>
-#include <openssl/crypto.h>
-#include <openssl/err.h>
-#include <openssl/ssl.h>
-#include "h2o.h"
-#include "h2o/configurator.h"
-
-struct proxy_configurator_t {
- h2o_configurator_t super;
- h2o_proxy_config_vars_t *vars;
- h2o_proxy_config_vars_t _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static int on_config_timeout_io(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)cmd->configurator;
- return h2o_configurator_scanf(cmd, node, "%" SCNu64, &self->vars->io_timeout);
-}
-
-static int on_config_timeout_keepalive(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)cmd->configurator;
- return h2o_configurator_scanf(cmd, node, "%" SCNu64, &self->vars->keepalive_timeout);
-}
-
-static int on_config_preserve_host(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)cmd->configurator;
- ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
- if (ret == -1)
- return -1;
- self->vars->preserve_host = (int)ret;
- return 0;
-}
-
-static int on_config_proxy_protocol(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)cmd->configurator;
- ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
- if (ret == -1)
- return -1;
- self->vars->use_proxy_protocol = (int)ret;
- return 0;
-}
-
-static int on_config_websocket_timeout(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)cmd->configurator;
- return h2o_configurator_scanf(cmd, node, "%" SCNu64, &self->vars->websocket.timeout);
-}
-
-static int on_config_websocket(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)cmd->configurator;
- ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
- if (ret == -1)
- return -1;
- self->vars->websocket.enabled = (int)ret;
- return 0;
-}
-
-static SSL_CTX *create_ssl_ctx(void)
-{
- SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
- SSL_CTX_set_options(ctx, SSL_CTX_get_options(ctx) | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
- return ctx;
-}
-
-static h2o_cache_t *create_ssl_session_cache(size_t capacity, uint64_t duration)
-{
- return h2o_cache_create(H2O_CACHE_FLAG_MULTITHREADED, capacity, duration, h2o_socket_ssl_destroy_session_cache_entry);
-}
-
-static void update_ssl_ctx(SSL_CTX **ctx, X509_STORE *cert_store, int verify_mode, h2o_cache_t **session_cache)
-{
- assert(*ctx != NULL);
-
- /* inherit the properties that weren't specified */
- if (cert_store == NULL)
- cert_store = SSL_CTX_get_cert_store(*ctx);
- X509_STORE_up_ref(cert_store);
- if (verify_mode == -1)
- verify_mode = SSL_CTX_get_verify_mode(*ctx);
- h2o_cache_t *new_session_cache;
- if (session_cache == NULL) {
- h2o_cache_t *current = h2o_socket_ssl_get_session_cache(*ctx);
- new_session_cache =
- current == NULL ? NULL : create_ssl_session_cache(h2o_cache_get_capacity(current), h2o_cache_get_duration(current));
- } else {
- new_session_cache = *session_cache;
- }
-
- /* free the existing context */
- if (*ctx != NULL)
- SSL_CTX_free(*ctx);
-
- /* create new ctx */
- *ctx = create_ssl_ctx();
- SSL_CTX_set_cert_store(*ctx, cert_store);
- SSL_CTX_set_verify(*ctx, verify_mode, NULL);
- if (new_session_cache != NULL)
- h2o_socket_ssl_set_session_cache(*ctx, new_session_cache);
-}
-
-static int on_config_ssl_verify_peer(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)cmd->configurator;
- ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
- if (ret == -1)
- return -1;
-
- update_ssl_ctx(&self->vars->ssl_ctx, NULL, ret != 0 ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE,
- NULL);
-
- return 0;
-}
-
-static int on_config_ssl_cafile(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)cmd->configurator;
- X509_STORE *store = X509_STORE_new();
- int ret = -1;
-
- if (X509_STORE_load_locations(store, node->data.scalar, NULL) == 1) {
- update_ssl_ctx(&self->vars->ssl_ctx, store, -1, NULL);
- ret = 0;
- } else {
- h2o_configurator_errprintf(cmd, node, "failed to load certificates file:%s", node->data.scalar);
- ERR_print_errors_fp(stderr);
- }
-
- X509_STORE_free(store);
- return ret;
-}
-
-static int on_config_ssl_session_cache(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)cmd->configurator;
- size_t capacity = 0;
- uint64_t duration = 0;
- h2o_cache_t *current_cache = h2o_socket_ssl_get_session_cache(self->vars->ssl_ctx);
-
- switch (node->type) {
- case YOML_TYPE_SCALAR:
- if (strcasecmp(node->data.scalar, "OFF") == 0) {
- if (current_cache != NULL) {
- /* set the cache NULL */
- h2o_cache_t *empty_cache = NULL;
- update_ssl_ctx(&self->vars->ssl_ctx, NULL, -1, &empty_cache);
- }
- return 0;
- } else if (strcasecmp(node->data.scalar, "ON") == 0) {
- /* use default values */
- capacity = H2O_DEFAULT_PROXY_SSL_SESSION_CACHE_CAPACITY;
- duration = H2O_DEFAULT_PROXY_SSL_SESSION_CACHE_DURATION;
- } else {
- h2o_configurator_errprintf(cmd, node, "scalar argument must be either of: `OFF`, `ON`");
- return -1;
- }
- break;
- case YOML_TYPE_MAPPING: {
- size_t i;
- for (i = 0; i != node->data.mapping.size; ++i) {
- yoml_t *key = node->data.mapping.elements[i].key;
- yoml_t *value = node->data.mapping.elements[i].value;
- if (key->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, key, "key must be a scalar");
- return -1;
- }
- if (strcasecmp(key->data.scalar, "capacity") == 0) {
- if (h2o_configurator_scanf(cmd, value, "%zu", &capacity) != 0)
- return -1;
- if (capacity == 0) {
- h2o_configurator_errprintf(cmd, key, "capacity must be greater than zero");
- return -1;
- }
- } else if (strcasecmp(key->data.scalar, "lifetime") == 0) {
- unsigned lifetime = 0;
- if (h2o_configurator_scanf(cmd, value, "%u", &lifetime) != 0)
- return -1;
- if (lifetime == 0) {
- h2o_configurator_errprintf(cmd, key, "lifetime must be greater than zero");
- return -1;
- }
- duration = (uint64_t)lifetime * 1000;
- } else {
- h2o_configurator_errprintf(cmd, key, "key must be either of: `capacity`, `lifetime`");
- return -1;
- }
- }
- if (capacity == 0 || duration == 0) {
- h2o_configurator_errprintf(cmd, node, "`capacity` and `lifetime` are required");
- return -1;
- }
- } break;
- default:
- h2o_configurator_errprintf(cmd, node, "node must be a scalar or a mapping");
- return -1;
- }
-
- if (current_cache != NULL) {
- size_t current_capacity = h2o_cache_get_capacity(current_cache);
- uint64_t current_duration = h2o_cache_get_duration(current_cache);
- if (capacity == current_capacity && duration == current_duration) {
- /* parameters aren't changed, so reuse it */
- return 0;
- }
- }
-
- h2o_cache_t *new_cache = create_ssl_session_cache(capacity, duration);
- update_ssl_ctx(&self->vars->ssl_ctx, NULL, -1, &new_cache);
- return 0;
-}
-
-static int on_config_reverse_url(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)cmd->configurator;
- h2o_url_t parsed;
-
- if (h2o_url_parse(node->data.scalar, SIZE_MAX, &parsed) != 0) {
- h2o_configurator_errprintf(cmd, node, "failed to parse URL: %s\n", node->data.scalar);
- return -1;
- }
- if (self->vars->keepalive_timeout != 0 && self->vars->use_proxy_protocol) {
- h2o_configurator_errprintf(cmd, node, "please either set `proxy.use-proxy-protocol` to `OFF` or disable keep-alive by "
- "setting `proxy.timeout.keepalive` to zero; the features are mutually exclusive");
- return -1;
- }
-
- if (self->vars->headers_cmds != NULL)
- h2o_mem_addref_shared(self->vars->headers_cmds);
-
- /* register */
- h2o_proxy_register_reverse_proxy(ctx->pathconf, &parsed, self->vars);
-
- return 0;
-}
-
-static int on_config_emit_x_forwarded_headers(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
- if (ret == -1)
- return -1;
- ctx->globalconf->proxy.emit_x_forwarded_headers = (int)ret;
- return 0;
-}
-
-static int on_config_emit_via_header(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
- if (ret == -1)
- return -1;
- ctx->globalconf->proxy.emit_via_header = (int)ret;
- return 0;
-}
-
-static int on_config_preserve_x_forwarded_proto(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
- if (ret == -1)
- return -1;
- ctx->globalconf->proxy.preserve_x_forwarded_proto = (int)ret;
- return 0;
-}
-
-static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)_self;
-
- memcpy(self->vars + 1, self->vars, sizeof(*self->vars));
- if (self->vars[1].headers_cmds != NULL)
- h2o_mem_addref_shared(self->vars[1].headers_cmds);
- ++self->vars;
-
- if (ctx->pathconf == NULL && ctx->hostconf == NULL) {
- /* is global conf, setup the default SSL context */
- self->vars->ssl_ctx = create_ssl_ctx();
- char *ca_bundle = h2o_configurator_get_cmd_path("share/h2o/ca-bundle.crt");
- if (SSL_CTX_load_verify_locations(self->vars->ssl_ctx, ca_bundle, NULL) != 1)
- fprintf(stderr, "Warning: failed to load the default certificates file at %s. Proxying to HTTPS servers may fail.\n",
- ca_bundle);
- free(ca_bundle);
- SSL_CTX_set_verify(self->vars->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
- h2o_cache_t *ssl_session_cache =
- create_ssl_session_cache(H2O_DEFAULT_PROXY_SSL_SESSION_CACHE_CAPACITY, H2O_DEFAULT_PROXY_SSL_SESSION_CACHE_DURATION);
- h2o_socket_ssl_set_session_cache(self->vars->ssl_ctx, ssl_session_cache);
- } else {
- SSL_CTX_up_ref(self->vars->ssl_ctx);
- }
-
- return 0;
-}
-
-static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct proxy_configurator_t *self = (void *)_self;
-
- if (ctx->pathconf == NULL && ctx->hostconf == NULL) {
- /* is global conf */
- ctx->globalconf->proxy.io_timeout = self->vars->io_timeout;
- ctx->globalconf->proxy.ssl_ctx = self->vars->ssl_ctx;
- } else {
- SSL_CTX_free(self->vars->ssl_ctx);
- }
-
- if (self->vars->headers_cmds != NULL)
- h2o_mem_release_shared(self->vars->headers_cmds);
-
- --self->vars;
- return 0;
-}
-
-static h2o_headers_command_t **get_headers_commands(h2o_configurator_t *_self)
-{
- struct proxy_configurator_t *self = (void *)_self;
- return &self->vars->headers_cmds;
-}
-
-void h2o_proxy_register_configurator(h2o_globalconf_t *conf)
-{
- struct proxy_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
-
- /* set default vars */
- c->vars = c->_vars_stack;
- c->vars->io_timeout = H2O_DEFAULT_PROXY_IO_TIMEOUT;
- c->vars->keepalive_timeout = 2000;
- c->vars->websocket.enabled = 0; /* have websocket proxying disabled by default; until it becomes non-experimental */
- c->vars->websocket.timeout = H2O_DEFAULT_PROXY_WEBSOCKET_TIMEOUT;
-
- /* setup handlers */
- c->super.enter = on_config_enter;
- c->super.exit = on_config_exit;
- h2o_configurator_define_command(
- &c->super, "proxy.reverse.url",
- H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR | H2O_CONFIGURATOR_FLAG_DEFERRED, on_config_reverse_url);
- h2o_configurator_define_command(&c->super, "proxy.preserve-host",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_preserve_host);
- h2o_configurator_define_command(&c->super, "proxy.proxy-protocol",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_proxy_protocol);
- h2o_configurator_define_command(&c->super, "proxy.timeout.io",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_timeout_io);
- h2o_configurator_define_command(&c->super, "proxy.timeout.keepalive",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_timeout_keepalive);
- h2o_configurator_define_command(&c->super, "proxy.websocket",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_websocket);
- h2o_configurator_define_command(&c->super, "proxy.websocket.timeout",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_websocket_timeout);
- h2o_configurator_define_command(&c->super, "proxy.ssl.verify-peer",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_ssl_verify_peer);
- h2o_configurator_define_command(&c->super, "proxy.ssl.cafile",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_ssl_cafile);
- h2o_configurator_define_command(&c->super, "proxy.ssl.session-cache", H2O_CONFIGURATOR_FLAG_ALL_LEVELS,
- on_config_ssl_session_cache);
- h2o_configurator_define_command(&c->super, "proxy.preserve-x-forwarded-proto",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_preserve_x_forwarded_proto);
- h2o_configurator_define_command(&c->super, "proxy.emit-x-forwarded-headers",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_emit_x_forwarded_headers);
- h2o_configurator_define_command(&c->super, "proxy.emit-via-header",
- H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_emit_via_header);
- h2o_configurator_define_headers_commands(conf, &c->super, "proxy.header", get_headers_commands);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/redirect.c b/web/server/h2o/libh2o/lib/handler/configurator/redirect.c
deleted file mode 100644
index 4ebbb99c0..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/redirect.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 "h2o.h"
-#include "h2o/configurator.h"
-
-static int on_config(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- const char *dest;
- int status = 302; /* default is temporary redirect */
- int internal = 0; /* default is external redirect */
- yoml_t *t;
-
- switch (node->type) {
- case YOML_TYPE_SCALAR:
- dest = node->data.scalar;
- break;
- case YOML_TYPE_MAPPING:
- if ((t = yoml_get(node, "url")) == NULL) {
- h2o_configurator_errprintf(cmd, node, "mandatory property `url` is missing");
- return -1;
- }
- if (t->type != YOML_TYPE_SCALAR) {
- h2o_configurator_errprintf(cmd, t, "property `url` must be a string");
- return -1;
- }
- dest = t->data.scalar;
- if ((t = yoml_get(node, "status")) == NULL) {
- h2o_configurator_errprintf(cmd, node, "mandatory property `status` is missing");
- return -1;
- }
- if (h2o_configurator_scanf(cmd, t, "%d", &status) != 0)
- return -1;
- if (!(300 <= status && status <= 399)) {
- h2o_configurator_errprintf(cmd, t, "value of property `status` should be within 300 to 399");
- return -1;
- }
- if ((t = yoml_get(node, "internal")) != NULL) {
- if ((internal = (int)h2o_configurator_get_one_of(cmd, t, "NO,YES")) == -1)
- return -1;
- }
- break;
- default:
- h2o_configurator_errprintf(cmd, node, "value must be a string or a mapping");
- return -1;
- }
-
- h2o_redirect_register(ctx->pathconf, internal, status, dest);
-
- return 0;
-}
-
-void h2o_redirect_register_configurator(h2o_globalconf_t *conf)
-{
- h2o_configurator_t *c = h2o_configurator_create(conf, sizeof(*c));
-
- h2o_configurator_define_command(c, "redirect", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_DEFERRED, on_config);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/reproxy.c b/web/server/h2o/libh2o/lib/handler/configurator/reproxy.c
deleted file mode 100644
index 21650e4fb..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/reproxy.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2015 Daisuke Maki, DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <inttypes.h>
-#include "h2o.h"
-#include "h2o/configurator.h"
-
-struct config_t {
- int enabled;
-};
-
-struct reproxy_configurator_t {
- h2o_configurator_t super;
- struct config_t *vars, _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static int on_config_reproxy(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct reproxy_configurator_t *self = (void *)cmd->configurator;
-
- ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON");
- if (ret == -1)
- return -1;
- self->vars->enabled = (int)ret;
-
- return 0;
-}
-
-static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct reproxy_configurator_t *self = (void *)_self;
-
- self->vars[1] = self->vars[0];
- ++self->vars;
- return 0;
-}
-
-static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct reproxy_configurator_t *self = (void *)_self;
-
- if (ctx->pathconf != NULL && self->vars->enabled != 0)
- h2o_reproxy_register(ctx->pathconf);
-
- --self->vars;
- return 0;
-}
-
-void h2o_reproxy_register_configurator(h2o_globalconf_t *conf)
-{
- struct reproxy_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
-
- /* set default vars */
- c->vars = c->_vars_stack;
-
- /* setup handlers */
- c->super.enter = on_config_enter;
- c->super.exit = on_config_exit;
-
- /* reproxy: ON | OFF */
- h2o_configurator_define_command(&c->super, "reproxy", H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_reproxy);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/status.c b/web/server/h2o/libh2o/lib/handler/configurator/status.c
deleted file mode 100644
index 8645aa33d..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/status.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 "h2o.h"
-#include "h2o/configurator.h"
-
-static int on_config_status(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- switch (h2o_configurator_get_one_of(cmd, node, "OFF,ON")) {
- case 0: /* OFF */
- return 0;
- case 1: /* ON */
- h2o_status_register(ctx->pathconf);
- return 0;
- default: /* error */
- return -1;
- }
-}
-
-struct st_status_configurator {
- h2o_configurator_t super;
- int stack;
- int duration_stats;
-};
-
-static int on_config_duration_stats(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_status_configurator *c = (void *)cmd->configurator;
- ssize_t ret;
- switch (ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON")) {
- case 0: /* OFF */
- case 1: /* ON */
- c->duration_stats = (int)ret;
- return 0;
- default: /* error */
- return -1;
- }
-}
-
-int on_enter_status(h2o_configurator_t *_conf, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_status_configurator *c = (void *)_conf;
- c->stack++;
- return 0;
-}
-
-int on_exit_status(h2o_configurator_t *_conf, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct st_status_configurator *c = (void *)_conf;
- c->stack--;
- if (!c->stack && c->duration_stats) {
- h2o_duration_stats_register(ctx->globalconf);
- }
- return 0;
-}
-
-void h2o_status_register_configurator(h2o_globalconf_t *conf)
-{
- struct st_status_configurator *c = (void *)h2o_configurator_create(conf, sizeof(*c));
- c->super.enter = on_enter_status;
- c->super.exit = on_exit_status;
-
- h2o_configurator_define_command(&c->super, "status", H2O_CONFIGURATOR_FLAG_PATH | H2O_CONFIGURATOR_FLAG_DEFERRED |
- H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_status);
-
- h2o_configurator_define_command(&c->super, "duration-stats", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_duration_stats);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/configurator/throttle_resp.c b/web/server/h2o/libh2o/lib/handler/configurator/throttle_resp.c
deleted file mode 100644
index 61431f756..000000000
--- a/web/server/h2o/libh2o/lib/handler/configurator/throttle_resp.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2016 Justin Zhu
- *
- * 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 "h2o.h"
-#include "h2o/configurator.h"
-
-struct throttle_resp_config_vars_t {
- int on;
-};
-
-struct throttle_resp_configurator_t {
- h2o_configurator_t super;
- struct throttle_resp_config_vars_t *vars, _vars_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
-};
-
-static int on_config_throttle_resp(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct throttle_resp_configurator_t *self = (void *)cmd->configurator;
-
- if ((self->vars->on = (int)h2o_configurator_get_one_of(cmd, node, "OFF,ON")) == -1)
- return -1;
- return 0;
-}
-
-static int on_config_enter(h2o_configurator_t *configurator, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct throttle_resp_configurator_t *self = (void *)configurator;
-
- ++self->vars;
- self->vars[0] = self->vars[-1];
- return 0;
-}
-
-static int on_config_exit(h2o_configurator_t *configurator, h2o_configurator_context_t *ctx, yoml_t *node)
-{
- struct throttle_resp_configurator_t *self = (void *)configurator;
-
- if (ctx->pathconf != NULL && self->vars->on)
- h2o_throttle_resp_register(ctx->pathconf);
-
- --self->vars;
- return 0;
-}
-
-void h2o_throttle_resp_register_configurator(h2o_globalconf_t *conf)
-{
- struct throttle_resp_configurator_t *c = (void *)h2o_configurator_create(conf, sizeof(*c));
-
- c->super.enter = on_config_enter;
- c->super.exit = on_config_exit;
- h2o_configurator_define_command(&c->super, "throttle-response",
- H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
- on_config_throttle_resp);
- c->vars = c->_vars_stack;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/errordoc.c b/web/server/h2o/libh2o/lib/handler/errordoc.c
deleted file mode 100644
index 72744f358..000000000
--- a/web/server/h2o/libh2o/lib/handler/errordoc.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 "h2o.h"
-
-/* used to rewrite status code to the original code */
-struct st_errordoc_prefilter_t {
- h2o_req_prefilter_t super;
- h2o_headers_t req_headers;
- int status;
- const char *reason;
- h2o_headers_t res_headers;
-};
-
-/* used to capture an error response */
-struct st_errordoc_filter_t {
- h2o_filter_t super;
- H2O_VECTOR(h2o_errordoc_t) errordocs;
-};
-
-static void add_header(h2o_mem_pool_t *pool, h2o_headers_t *headers, const h2o_header_t *header)
-{
- h2o_vector_reserve(pool, headers, headers->size + 1);
- headers->entries[headers->size++] = *header;
-}
-
-static void on_prefilter_setup_stream(h2o_req_prefilter_t *_self, h2o_req_t *req, h2o_ostream_t **slot)
-{
- struct st_errordoc_prefilter_t *self = (void *)_self;
- h2o_headers_t headers_merged = {NULL};
- size_t i;
-
- /* restore request headers (for logging) and response status */
- req->headers = self->req_headers;
- req->res.status = self->status;
- req->res.reason = self->reason;
-
- /* generate response headers (by merging the preserved and given) */
- for (i = 0; i != self->res_headers.size; ++i)
- add_header(&req->pool, &headers_merged, self->res_headers.entries + i);
- for (i = 0; i != req->res.headers.size; ++i) {
- const h2o_header_t *header = req->res.headers.entries + i;
- if (header->name == &H2O_TOKEN_CONTENT_TYPE->buf || header->name == &H2O_TOKEN_CONTENT_LANGUAGE->buf ||
- header->name == &H2O_TOKEN_SET_COOKIE->buf)
- add_header(&req->pool, &headers_merged, header);
- }
- req->res.headers = headers_merged;
-
- h2o_setup_next_prefilter(&self->super, req, slot);
-}
-
-static void on_ostream_send(h2o_ostream_t *self, h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state)
-{
- /* nothing to do */
-}
-
-static int prefilter_is_registered(h2o_req_t *req)
-{
- h2o_req_prefilter_t *prefilter;
- for (prefilter = req->prefilters; prefilter != NULL; prefilter = prefilter->next)
- if (prefilter->on_setup_ostream == on_prefilter_setup_stream)
- return 1;
- return 0;
-}
-
-static void on_filter_setup_ostream(h2o_filter_t *_self, h2o_req_t *req, h2o_ostream_t **slot)
-{
- struct st_errordoc_filter_t *self = (void *)_self;
- h2o_errordoc_t *errordoc;
- struct st_errordoc_prefilter_t *prefilter;
- h2o_iovec_t method;
- h2o_ostream_t *ostream;
- size_t i;
-
- if (req->res.status >= 400 && !prefilter_is_registered(req)) {
- size_t i;
- for (i = 0; i != self->errordocs.size; ++i) {
- errordoc = self->errordocs.entries + i;
- if (errordoc->status == req->res.status)
- goto Found;
- }
- }
-
- /* bypass to the next filter */
- h2o_setup_next_ostream(req, slot);
- return;
-
-Found:
- /* register prefilter that rewrites the status code after the internal redirect is processed */
- prefilter = (void *)h2o_add_prefilter(req, sizeof(*prefilter));
- prefilter->super.on_setup_ostream = on_prefilter_setup_stream;
- prefilter->req_headers = req->headers;
- prefilter->status = req->res.status;
- prefilter->reason = req->res.reason;
- prefilter->res_headers = (h2o_headers_t){NULL};
- for (i = 0; i != req->res.headers.size; ++i) {
- const h2o_header_t *header = req->res.headers.entries + i;
- if (!(header->name == &H2O_TOKEN_CONTENT_TYPE->buf || header->name == &H2O_TOKEN_CONTENT_LANGUAGE->buf))
- add_header(&req->pool, &prefilter->res_headers, header);
- }
- /* redirect internally to the error document */
- method = req->method;
- if (h2o_memis(method.base, method.len, H2O_STRLIT("POST")))
- method = h2o_iovec_init(H2O_STRLIT("GET"));
- req->headers = (h2o_headers_t){NULL};
- req->res.headers = (h2o_headers_t){NULL};
- h2o_send_redirect_internal(req, method, errordoc->url.base, errordoc->url.len, 0);
- /* create fake ostream that swallows the contents emitted by the generator */
- ostream = h2o_add_ostream(req, sizeof(*ostream), slot);
- ostream->do_send = on_ostream_send;
-}
-
-void h2o_errordoc_register(h2o_pathconf_t *pathconf, h2o_errordoc_t *errdocs, size_t cnt)
-{
- struct st_errordoc_filter_t *self = (void *)h2o_create_filter(pathconf, sizeof(*self));
- size_t i;
-
- self->super.on_setup_ostream = on_filter_setup_ostream;
- h2o_vector_reserve(NULL, &self->errordocs, cnt);
- self->errordocs.size = cnt;
- for (i = 0; i != cnt; ++i) {
- const h2o_errordoc_t *src = errdocs + i;
- h2o_errordoc_t *dst = self->errordocs.entries + i;
- dst->status = src->status;
- dst->url = h2o_strdup(NULL, src->url.base, src->url.len);
- }
-}
diff --git a/web/server/h2o/libh2o/lib/handler/expires.c b/web/server/h2o/libh2o/lib/handler/expires.c
deleted file mode 100644
index c77225649..000000000
--- a/web/server/h2o/libh2o/lib/handler/expires.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2015 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 <assert.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "h2o.h"
-
-struct st_expires_t {
- h2o_filter_t super;
- int mode;
- h2o_iovec_t value;
-};
-
-static void on_setup_ostream(h2o_filter_t *_self, h2o_req_t *req, h2o_ostream_t **slot)
-{
- struct st_expires_t *self = (void *)_self;
-
- switch (req->res.status) {
- case 200:
- case 201:
- case 204:
- case 206:
- case 301:
- case 302:
- case 303:
- case 304:
- case 307:
- switch (self->mode) {
- case H2O_EXPIRES_MODE_ABSOLUTE:
- h2o_set_header(&req->pool, &req->res.headers, H2O_TOKEN_EXPIRES, self->value.base, self->value.len, 0);
- break;
- case H2O_EXPIRES_MODE_MAX_AGE:
- h2o_set_header_token(&req->pool, &req->res.headers, H2O_TOKEN_CACHE_CONTROL, self->value.base, self->value.len);
- break;
- default:
- assert(0);
- break;
- }
- break;
- default:
- break;
- }
-
- h2o_setup_next_ostream(req, slot);
-}
-
-void h2o_expires_register(h2o_pathconf_t *pathconf, h2o_expires_args_t *args)
-{
- struct st_expires_t *self = (void *)h2o_create_filter(pathconf, sizeof(*self));
- self->super.on_setup_ostream = on_setup_ostream;
- self->mode = args->mode;
- switch (args->mode) {
- case H2O_EXPIRES_MODE_ABSOLUTE:
- self->value = h2o_strdup(NULL, args->data.absolute, SIZE_MAX);
- break;
- case H2O_EXPIRES_MODE_MAX_AGE:
- self->value.base = h2o_mem_alloc(128);
- self->value.len = sprintf(self->value.base, "max-age=%" PRIu64, args->data.max_age);
- break;
- default:
- assert(0);
- break;
- }
-}
diff --git a/web/server/h2o/libh2o/lib/handler/fastcgi.c b/web/server/h2o/libh2o/lib/handler/fastcgi.c
deleted file mode 100644
index d6bcf9ede..000000000
--- a/web/server/h2o/libh2o/lib/handler/fastcgi.c
+++ /dev/null
@@ -1,856 +0,0 @@
-/*
- * Copyright (c) 2015-2016 DeNA Co., Ltd. Kazuho Oku
- *
- * 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 <inttypes.h>
-#include <stdio.h>
-#include "picohttpparser.h"
-#include "h2o.h"
-
-#define FCGI_VERSION_1 1
-
-#define FCGI_RESPONDER 1
-#define FCGI_KEEP_CONN 1
-
-#define FCGI_BEGIN_REQUEST 1
-#define FCGI_END_REQUEST 3
-#define FCGI_PARAMS 4
-#define FCGI_STDIN 5
-#define FCGI_STDOUT 6
-#define FCGI_STDERR 7
-#define FCGI_DATA 8
-
-#define FCGI_RECORD_HEADER_SIZE (sizeof(struct st_fcgi_record_header_t))
-#define FCGI_BEGIN_REQUEST_BODY_SIZE 8
-
-#define MODULE_NAME "lib/handler/fastcgi.c"
-
-#define APPEND_BLOCKSIZE 512 /* the size should be small enough to be allocated within the buffer of the memory pool */
-
-struct st_fcgi_record_header_t {
- uint8_t version;
- uint8_t type;
- uint16_t requestId;
- uint16_t contentLength;
- uint8_t paddingLength;
- uint8_t reserved;
-};
-
-struct st_fcgi_begin_request_body_t {
- uint16_t role;
- uint8_t flags;
- uint8_t reserved[5];
-};
-
-typedef H2O_VECTOR(h2o_iovec_t) iovec_vector_t;
-
-struct st_fcgi_context_t {
- h2o_fastcgi_handler_t *handler;
- h2o_timeout_t io_timeout;
-};
-
-struct st_fcgi_generator_t {
- h2o_generator_t super;
- struct st_fcgi_context_t *ctx;
- h2o_req_t *req;
- h2o_socketpool_connect_request_t *connect_req;
- h2o_socket_t *sock;
- int sent_headers;
- size_t leftsize; /* remaining amount of the content to receive (or SIZE_MAX if unknown) */
- struct {
- h2o_doublebuffer_t sending;
- h2o_buffer_t *receiving;
- } resp;
- h2o_timeout_entry_t timeout;
-};
-
-struct st_h2o_fastcgi_handler_t {
- h2o_handler_t super;
- h2o_socketpool_t sockpool;
- h2o_fastcgi_config_vars_t config;
-};
-
-static void encode_uint16(void *_p, unsigned v)
-{
- unsigned char *p = _p;
- p[0] = (unsigned char)(v >> 8);
- p[1] = (unsigned char)v;
-}
-
-static void encode_record_header(void *p, uint8_t type, uint16_t reqId, uint16_t sz)
-{
- struct st_fcgi_record_header_t *header = p;
- header->version = FCGI_VERSION_1;
- header->type = type;
- encode_uint16(&header->requestId, reqId);
- encode_uint16(&header->contentLength, sz);
- header->paddingLength = 0;
- header->reserved = 0;
-}
-
-static void encode_begin_request(void *p, uint16_t reqId, uint16_t role, uint8_t flags)
-{
- encode_record_header(p, FCGI_BEGIN_REQUEST, reqId, FCGI_BEGIN_REQUEST_BODY_SIZE);
- struct st_fcgi_begin_request_body_t *body = (void *)((char *)p + FCGI_RECORD_HEADER_SIZE);
- encode_uint16(&body->role, role);
- body->flags = flags;
- memset(body->reserved, 0, sizeof(body->reserved));
-}
-
-static h2o_iovec_t create_begin_request(h2o_mem_pool_t *pool, uint16_t reqId, uint16_t role, uint8_t flags)
-{
- h2o_iovec_t rec = h2o_iovec_init(h2o_mem_alloc_pool(pool, FCGI_RECORD_HEADER_SIZE + FCGI_BEGIN_REQUEST_BODY_SIZE),
- FCGI_RECORD_HEADER_SIZE + FCGI_BEGIN_REQUEST_BODY_SIZE);
- encode_begin_request(rec.base, reqId, role, flags);
- return rec;
-}
-
-static h2o_iovec_t create_header(h2o_mem_pool_t *pool, uint8_t type, uint16_t reqId, uint16_t sz)
-{
- h2o_iovec_t rec = h2o_iovec_init(h2o_mem_alloc_pool(pool, FCGI_RECORD_HEADER_SIZE), FCGI_RECORD_HEADER_SIZE);
- encode_record_header(rec.base, type, reqId, sz);
- return rec;
-}
-
-static void decode_header(struct st_fcgi_record_header_t *decoded, const void *s)
-{
- memcpy(decoded, s, sizeof(*decoded));
- decoded->requestId = htons(decoded->requestId);
- decoded->contentLength = htons(decoded->contentLength);
-}
-
-static void *append(h2o_mem_pool_t *pool, iovec_vector_t *blocks, const void *s, size_t len)
-{
- h2o_iovec_t *slot;
-
- if (blocks->entries[blocks->size - 1].len + len > APPEND_BLOCKSIZE) {
- h2o_vector_reserve(pool, blocks, blocks->size + 1);
- slot = blocks->entries + blocks->size++;
- slot->base = h2o_mem_alloc_pool(pool, len < APPEND_BLOCKSIZE ? APPEND_BLOCKSIZE : len);
- slot->len = 0;
- } else {
- slot = blocks->entries + blocks->size - 1;
- }
-
- if (s != NULL)
- memcpy(slot->base + slot->len, s, len);
- slot->len += len;
-
- return slot->base + slot->len - len;
-}
-
-static char *encode_length_of_pair(char *p, size_t len)
-{
- if (len < 127) {
- *p++ = (char)len;
- } else {
- *p++ = (unsigned char)(len >> 24) | 0x80;
- *p++ = (unsigned char)(len >> 16);
- *p++ = (unsigned char)(len >> 8);
- *p++ = (unsigned char)len;
- }
- return p;
-}
-
-static void *append_pair(h2o_mem_pool_t *pool, iovec_vector_t *blocks, const char *name, size_t namelen, const char *value,
- size_t valuelen)
-{
- char lenbuf[8];
- void *name_buf;
-
- append(pool, blocks, lenbuf, encode_length_of_pair(encode_length_of_pair(lenbuf, namelen), valuelen) - lenbuf);
- name_buf = append(pool, blocks, name, namelen);
- if (valuelen != 0)
- append(pool, blocks, value, valuelen);
-
- return name_buf;
-}
-
-static void append_address_info(h2o_req_t *req, iovec_vector_t *vecs, const char *addrlabel, size_t addrlabel_len,
- const char *portlabel, size_t portlabel_len, socklen_t (*cb)(h2o_conn_t *conn, struct sockaddr *))
-{
- struct sockaddr_storage ss;
- socklen_t sslen;
- char buf[NI_MAXHOST];
-
- if ((sslen = cb(req->conn, (void *)&ss)) == 0)
- return;
-
- size_t l = h2o_socket_getnumerichost((void *)&ss, sslen, buf);
- if (l != SIZE_MAX)
- append_pair(&req->pool, vecs, addrlabel, addrlabel_len, buf, l);
- int32_t port = h2o_socket_getport((void *)&ss);
- if (port != -1) {
- char buf[6];
- int l = sprintf(buf, "%" PRIu16, (uint16_t)port);
- append_pair(&req->pool, vecs, portlabel, portlabel_len, buf, (size_t)l);
- }
-}
-
-static int envname_is_headername(const h2o_iovec_t *env, const h2o_iovec_t *header)
-{
- const char *ep, *hp, *hend;
-
- if (env->len != 5 + header->len)
- return 0;
- if (memcmp(env->base, "HTTP_", 5) != 0)
- return 0;
- for (ep = env->base + 5, hp = header->base, hend = hp + header->len; hp < hend; ++ep, ++hp)
- if (*ep != h2o_toupper(*hp))
- return 0;
- return 1;
-}
-
-static void append_params(h2o_req_t *req, iovec_vector_t *vecs, h2o_fastcgi_config_vars_t *config)
-{
- h2o_iovec_t path_info = {NULL};
-
- /* CONTENT_LENGTH */
- if (req->entity.base != NULL) {
- char buf[32];
- int l = sprintf(buf, "%zu", req->entity.len);
- append_pair(&req->pool, vecs, H2O_STRLIT("CONTENT_LENGTH"), buf, (size_t)l);
- }
- /* SCRIPT_FILENAME, SCRIPT_NAME, PATH_INFO */
- if (req->filereq != NULL) {
- h2o_filereq_t *filereq = req->filereq;
- append_pair(&req->pool, vecs, H2O_STRLIT("SCRIPT_FILENAME"), filereq->local_path.base, filereq->local_path.len);
- append_pair(&req->pool, vecs, H2O_STRLIT("SCRIPT_NAME"), filereq->script_name.base, filereq->script_name.len);
- path_info = filereq->path_info;
- } else {
- append_pair(&req->pool, vecs, H2O_STRLIT("SCRIPT_NAME"), NULL, 0);
- path_info = req->path_normalized;
- }
- if (path_info.base != NULL)
- append_pair(&req->pool, vecs, H2O_STRLIT("PATH_INFO"), path_info.base, path_info.len);
- /* DOCUMENT_ROOT and PATH_TRANSLATED */
- if (config->document_root.base != NULL) {
- append_pair(&req->pool, vecs, H2O_STRLIT("DOCUMENT_ROOT"), config->document_root.base, config->document_root.len);
- if (path_info.base != NULL) {
- append_pair(&req->pool, vecs, H2O_STRLIT("PATH_TRANSLATED"), NULL, config->document_root.len + path_info.len);
- char *dst_end = vecs->entries[vecs->size - 1].base + vecs->entries[vecs->size - 1].len;
- memcpy(dst_end - path_info.len, path_info.base, path_info.len);
- memcpy(dst_end - path_info.len - config->document_root.len, config->document_root.base, config->document_root.len);
- }
- }
- /* QUERY_STRING (and adjust PATH_INFO) */
- if (req->query_at != SIZE_MAX) {
- append_pair(&req->pool, vecs, H2O_STRLIT("QUERY_STRING"), req->path.base + req->query_at + 1,
- req->path.len - (req->query_at + 1));
- } else {
- append_pair(&req->pool, vecs, H2O_STRLIT("QUERY_STRING"), NULL, 0);
- }
- /* REMOTE_ADDR & REMOTE_PORT */
- append_address_info(req, vecs, H2O_STRLIT("REMOTE_ADDR"), H2O_STRLIT("REMOTE_PORT"), req->conn->callbacks->get_peername);
- { /* environment variables (REMOTE_USER, etc.) */
- size_t i;
- for (i = 0; i != req->env.size; i += 2) {
- h2o_iovec_t *name = req->env.entries + i, *value = name + 1;
- append_pair(&req->pool, vecs, name->base, name->len, value->base, value->len);
- }
- }
- /* REQUEST_METHOD */
- append_pair(&req->pool, vecs, H2O_STRLIT("REQUEST_METHOD"), req->method.base, req->method.len);
- /* HTTP_HOST & REQUEST_URI */
- if (config->send_delegated_uri) {
- append_pair(&req->pool, vecs, H2O_STRLIT("HTTP_HOST"), req->authority.base, req->authority.len);
- append_pair(&req->pool, vecs, H2O_STRLIT("REQUEST_URI"), req->path.base, req->path.len);
- } else {
- append_pair(&req->pool, vecs, H2O_STRLIT("HTTP_HOST"), req->input.authority.base, req->input.authority.len);
- append_pair(&req->pool, vecs, H2O_STRLIT("REQUEST_URI"), req->input.path.base, req->input.path.len);
- }
- /* SERVER_ADDR & SERVER_PORT */
- append_address_info(req, vecs, H2O_STRLIT("SERVER_ADDR"), H2O_STRLIT("SERVER_PORT"), req->conn->callbacks->get_sockname);
- /* SERVER_NAME */
- append_pair(&req->pool, vecs, H2O_STRLIT("SERVER_NAME"), req->hostconf->authority.host.base, req->hostconf->authority.host.len);
- { /* SERVER_PROTOCOL */
- char buf[sizeof("HTTP/1.1")];
- size_t l = h2o_stringify_protocol_version(buf, req->version);
- append_pair(&req->pool, vecs, H2O_STRLIT("SERVER_PROTOCOL"), buf, l);
- }
- /* SERVER_SOFTWARE */
- append_pair(&req->pool, vecs, H2O_STRLIT("SERVER_SOFTWARE"), req->conn->ctx->globalconf->server_name.base,
- req->conn->ctx->globalconf->server_name.len);
- /* set HTTPS: on if necessary */
- if (req->scheme == &H2O_URL_SCHEME_HTTPS)
- append_pair(&req->pool, vecs, H2O_STRLIT("HTTPS"), H2O_STRLIT("on"));
- { /* headers */
- const h2o_header_t *h = req->headers.entries, *h_end = h + req->headers.size;
- size_t cookie_length = 0;
- for (; h != h_end; ++h) {
- if (h->name == &H2O_TOKEN_CONTENT_TYPE->buf) {
- append_pair(&req->pool, vecs, H2O_STRLIT("CONTENT_TYPE"), h->value.base, h->value.len);
- } else if (h->name == &H2O_TOKEN_COOKIE->buf) {
- /* accumulate the length of the cookie, together with the separator */
- cookie_length += h->value.len + 1;
- } else {
- size_t i;
- for (i = 0; i != req->env.size; i += 2) {
- h2o_iovec_t *envname = req->env.entries + i;
- if (envname_is_headername(envname, h->name))
- goto NextHeader;
- }
- char *dst = append_pair(&req->pool, vecs, NULL, h->name->len + sizeof("HTTP_") - 1, h->value.base, h->value.len);
- const char *src = h->name->base, *src_end = src + h->name->len;
- *dst++ = 'H';
- *dst++ = 'T';
- *dst++ = 'T';
- *dst++ = 'P';
- *dst++ = '_';
- for (; src != src_end; ++src)
- *dst++ = *src == '-' ? '_' : h2o_toupper(*src);
- }
- NextHeader:;
- }
- if (cookie_length != 0) {
- /* emit the cookie merged */
- cookie_length -= 1;
- append_pair(&req->pool, vecs, H2O_STRLIT("HTTP_COOKIE"), NULL, cookie_length);
- char *dst = vecs->entries[vecs->size - 1].base + vecs->entries[vecs->size - 1].len - cookie_length;
- for (h = req->headers.entries;; ++h) {
- if (h->name == &H2O_TOKEN_COOKIE->buf) {
- if (cookie_length == h->value.len)
- break;
- memcpy(dst, h->value.base, h->value.len);
- dst += h->value.len;
- *dst++ = ';';
- cookie_length -= h->value.len + 1;
- }
- }
- memcpy(dst, h->value.base, h->value.len);
- }
- }
-}
-
-static void annotate_params(h2o_mem_pool_t *pool, iovec_vector_t *vecs, unsigned request_id, size_t max_record_size)
-{
- size_t index = 2, recsize = 0, header_slot = 1;
-
- while (index != vecs->size) {
- if (recsize + vecs->entries[index].len < max_record_size) {
- recsize += vecs->entries[index].len;
- ++index;
- } else {
- vecs->entries[header_slot] = create_header(pool, FCGI_PARAMS, request_id, max_record_size);
- if (recsize + vecs->entries[index].len == max_record_size) {
- h2o_vector_reserve(pool, vecs, vecs->size + 1);
- memmove(vecs->entries + index + 2, vecs->entries + index + 1,
- (vecs->size - (index + 1)) * sizeof(vecs->entries[0]));
- ++vecs->size;
- } else {
- h2o_vector_reserve(pool, vecs, vecs->size + 2);
- memmove(vecs->entries + index + 2, vecs->entries + index, (vecs->size - index) * sizeof(vecs->entries[0]));
- vecs->size += 2;
- size_t lastsz = max_record_size - recsize;
- vecs->entries[index].len = lastsz;
- vecs->entries[index + 2].base += lastsz;
- vecs->entries[index + 2].len -= lastsz;
- }
- header_slot = index + 1;
- index += 2;
- recsize = 0;
- }
- }
-
- vecs->entries[header_slot] = create_header(pool, FCGI_PARAMS, request_id, recsize);
- if (recsize != 0) {
- h2o_vector_reserve(pool, vecs, vecs->size + 1);
- vecs->entries[vecs->size++] = create_header(pool, FCGI_PARAMS, request_id, 0);
- }
-}
-
-static void build_request(h2o_req_t *req, iovec_vector_t *vecs, unsigned request_id, size_t max_record_size,
- h2o_fastcgi_config_vars_t *config)
-{
- *vecs = (iovec_vector_t){NULL};
-
- /* first entry is FCGI_BEGIN_REQUEST */
- h2o_vector_reserve(&req->pool, vecs, 5 /* we send at least 5 iovecs */);
- vecs->entries[0] =
- create_begin_request(&req->pool, request_id, FCGI_RESPONDER, config->keepalive_timeout != 0 ? FCGI_KEEP_CONN : 0);
- /* second entry is reserved for FCGI_PARAMS header */
- vecs->entries[1] = h2o_iovec_init(NULL, APPEND_BLOCKSIZE); /* dummy value set to prevent params being appended to the entry */
- vecs->size = 2;
- /* accumulate the params data, and annotate them with FCGI_PARAM headers */
- append_params(req, vecs, config);
- annotate_params(&req->pool, vecs, request_id, max_record_size);
- /* setup FCGI_STDIN headers */
- if (req->entity.len != 0) {
- size_t off = 0;
- for (; off + max_record_size < req->entity.len; off += max_record_size) {
- h2o_vector_reserve(&req->pool, vecs, vecs->size + 2);
- vecs->entries[vecs->size++] = create_header(&req->pool, FCGI_STDIN, request_id, max_record_size);
- vecs->entries[vecs->size++] = h2o_iovec_init(req->entity.base + off, max_record_size);
- }
- if (off != req->entity.len) {
- h2o_vector_reserve(&req->pool, vecs, vecs->size + 2);
- vecs->entries[vecs->size++] = create_header(&req->pool, FCGI_STDIN, request_id, req->entity.len - off);
- vecs->entries[vecs->size++] = h2o_iovec_init(req->entity.base + off, req->entity.len - off);
- }
- }
- h2o_vector_reserve(&req->pool, vecs, vecs->size + 1);
- vecs->entries[vecs->size++] = create_header(&req->pool, FCGI_STDIN, request_id, 0);
-}
-
-static void set_timeout(struct st_fcgi_generator_t *generator, h2o_timeout_t *timeout, h2o_timeout_cb cb)
-{
- if (h2o_timeout_is_linked(&generator->timeout))
- h2o_timeout_unlink(&generator->timeout);
-
- generator->timeout.cb = cb;
- h2o_timeout_link(generator->req->conn->ctx->loop, timeout, &generator->timeout);
-}
-
-static void close_generator(struct st_fcgi_generator_t *generator)
-{
- /* can be called more than once */
-
- if (h2o_timeout_is_linked(&generator->timeout))
- h2o_timeout_unlink(&generator->timeout);
- if (generator->connect_req != NULL) {
- h2o_socketpool_cancel_connect(generator->connect_req);
- generator->connect_req = NULL;
- }
- if (generator->sock != NULL) {
- h2o_socket_close(generator->sock);
- generator->sock = NULL;
- }
- if (generator->resp.sending.buf != NULL)
- h2o_doublebuffer_dispose(&generator->resp.sending);
- if (generator->resp.receiving != NULL)
- h2o_buffer_dispose(&generator->resp.receiving);
-}
-
-static void do_send(struct st_fcgi_generator_t *generator)
-{
- h2o_iovec_t vecs[1];
- size_t veccnt;
- int is_final;
-
- vecs[0] = h2o_doublebuffer_prepare(&generator->resp.sending, &generator->resp.receiving, generator->req->preferred_chunk_size);
- veccnt = vecs[0].len != 0 ? 1 : 0;
- if (generator->sock == NULL && vecs[0].len == generator->resp.sending.buf->size && generator->resp.receiving->size == 0) {
- is_final = 1;
- if (!(generator->leftsize == 0 || generator->leftsize == SIZE_MAX))
- generator->req->http1_is_persistent = 0;
- } else {
- if (veccnt == 0)
- return;
- is_final = 0;
- }
- h2o_send(generator->req, vecs, veccnt, is_final ? H2O_SEND_STATE_FINAL : H2O_SEND_STATE_IN_PROGRESS);
-}
-
-static void send_eos_and_close(struct st_fcgi_generator_t *generator, int can_keepalive)
-{
- if (generator->ctx->handler->config.keepalive_timeout != 0 && can_keepalive)
- h2o_socketpool_return(&generator->ctx->handler->sockpool, generator->sock);
- else
- h2o_socket_close(generator->sock);
- generator->sock = NULL;
-
- if (h2o_timeout_is_linked(&generator->timeout))
- h2o_timeout_unlink(&generator->timeout);
-
- if (generator->resp.sending.bytes_inflight == 0)
- do_send(generator);
-}
-
-static void errorclose(struct st_fcgi_generator_t *generator)
-{
- if (generator->sent_headers) {
- send_eos_and_close(generator, 0);
- } else {
- h2o_req_t *req = generator->req;
- close_generator(generator);
- h2o_send_error_503(req, "Internal Server Error", "Internal Server Error", 0);
- }
-}
-
-static int _isdigit(int ch)
-{
- return '0' <= ch && ch <= '9';
-}
-
-static int fill_headers(h2o_req_t *req, struct phr_header *headers, size_t num_headers)
-{
- size_t i;
-
- /* set the defaults */
- req->res.status = 200;
- req->res.reason = "OK";
- req->res.content_length = SIZE_MAX;
-
- for (i = 0; i != num_headers; ++i) {
- const h2o_token_t *token;
- h2o_strtolower((char *)headers[i].name, headers[i].name_len);
- if ((token = h2o_lookup_token(headers[i].name, headers[i].name_len)) != NULL) {
- if (token->proxy_should_drop_for_res) {
- /* skip */
- } else if (token == H2O_TOKEN_CONTENT_LENGTH) {
- if (req->res.content_length != SIZE_MAX) {
- h2o_req_log_error(req, MODULE_NAME, "received multiple content-length headers from fcgi");
- return -1;
- }
- if ((req->res.content_length = h2o_strtosize(headers[i].value, headers[i].value_len)) == SIZE_MAX) {
- h2o_req_log_error(req, MODULE_NAME, "failed to parse content-length header sent from fcgi: %.*s",
- (int)headers[i].value_len, headers[i].value);
- return -1;
- }
- } else {
- /*
- RFC 3875 defines three headers to have special meaning: Content-Type, Status, Location.
- Status is handled as below.
- Content-Type does not seem to have any need to be handled specially.
- RFC suggests abs-path-style Location headers should trigger an internal redirection, but is that how the web servers
- work?
- */
- h2o_add_header(&req->pool, &req->res.headers, token, NULL,
- h2o_strdup(&req->pool, headers[i].value, headers[i].value_len).base, headers[i].value_len);
- if (token == H2O_TOKEN_LINK)
- h2o_push_path_in_link_header(req, headers[i].value, headers[i].value_len);
- }
- } else if (h2o_memis(headers[i].name, headers[i].name_len, H2O_STRLIT("status"))) {
- h2o_iovec_t value = h2o_iovec_init(headers[i].value, headers[i].value_len);
- if (value.len < 3 || !(_isdigit(value.base[0]) && _isdigit(value.base[1]) && _isdigit(value.base[2])) ||
- (value.len >= 4 && value.base[3] != ' ')) {
- h2o_req_log_error(req, MODULE_NAME, "failed to parse Status header, got: %.*s", (int)value.len, value.base);
- return -1;
- }
- req->res.status = (value.base[0] - '0') * 100 + (value.base[1] - '0') * 10 + (value.base[2] - '0');
- req->res.reason = value.len >= 5 ? h2o_strdup(&req->pool, value.base + 4, value.len - 4).base : "OK";
- } else {
- h2o_iovec_t name_duped = h2o_strdup(&req->pool, headers[i].name, headers[i].name_len),
- value_duped = h2o_strdup(&req->pool, headers[i].value, headers[i].value_len);
- h2o_add_header_by_str(&req->pool, &req->res.headers, name_duped.base, name_duped.len, 0, NULL, value_duped.base,
- value_duped.len);
- }
- }
-
- return 0;
-}
-
-static void append_content(struct st_fcgi_generator_t *generator, const void *src, size_t len)
-{
- /* do not accumulate more than content-length bytes */
- if (generator->leftsize != SIZE_MAX) {
- if (generator->leftsize < len) {
- len = generator->leftsize;
- if (len == 0)
- return;
- }
- generator->leftsize -= len;
- }
-
- h2o_iovec_t reserved = h2o_buffer_reserve(&generator->resp.receiving, len);
- memcpy(reserved.base, src, len);
- generator->resp.receiving->size += len;
-}
-
-static int handle_stdin_record(struct st_fcgi_generator_t *generator, struct st_fcgi_record_header_t *header)
-{
- h2o_buffer_t *input = generator->sock->input;
- struct phr_header headers[100];
- size_t num_headers;
- int parse_result;
-
- if (header->contentLength == 0)
- return 0;
-
- if (generator->sent_headers) {
- /* simply accumulate the data to response buffer */
- append_content(generator, input->bytes + FCGI_RECORD_HEADER_SIZE, header->contentLength);
- return 0;
- }
-
- /* parse the headers using the input buffer (or keep it in response buffer and parse) */
- num_headers = sizeof(headers) / sizeof(headers[0]);
- if (generator->resp.receiving->size == 0) {
- parse_result = phr_parse_headers(input->bytes + FCGI_RECORD_HEADER_SIZE, header->contentLength, headers, &num_headers, 0);
- } else {
- size_t prevlen = generator->resp.receiving->size;
- memcpy(h2o_buffer_reserve(&generator->resp.receiving, header->contentLength).base, input->bytes + FCGI_RECORD_HEADER_SIZE,
- header->contentLength);
- generator->resp.receiving->size = prevlen + header->contentLength;
- parse_result =
- phr_parse_headers(generator->resp.receiving->bytes, generator->resp.receiving->size, headers, &num_headers, prevlen);
- }
- if (parse_result < 0) {
- if (parse_result == -2) {
- /* incomplete */
- if (generator->resp.receiving->size == 0) {
- memcpy(h2o_buffer_reserve(&generator->resp.receiving, header->contentLength).base,
- input->bytes + FCGI_RECORD_HEADER_SIZE, header->contentLength);
- generator->resp.receiving->size = header->contentLength;
- }
- return 0;
- } else {
- h2o_req_log_error(generator->req, MODULE_NAME, "received broken response");
- return -1;
- }
- }
-
- /* fill-in the headers, and start the response */
- if (fill_headers(generator->req, headers, num_headers) != 0)
- return -1;
- generator->leftsize = generator->req->res.content_length;
- h2o_start_response(generator->req, &generator->super);
- generator->sent_headers = 1;
-
- /* rest of the contents should be stored in the response buffer */
- if (generator->resp.receiving->size == 0) {
- size_t leftlen = header->contentLength - parse_result;
- if (leftlen != 0) {
- append_content(generator, input->bytes + FCGI_RECORD_HEADER_SIZE + parse_result, leftlen);
- }
- } else {
- h2o_buffer_consume(&generator->resp.receiving, parse_result);
- }
-
- return 0;
-}
-
-static void on_rw_timeout(h2o_timeout_entry_t *entry)
-{
- struct st_fcgi_generator_t *generator = H2O_STRUCT_FROM_MEMBER(struct st_fcgi_generator_t, timeout, entry);
-
- h2o_req_log_error(generator->req, MODULE_NAME, "I/O timeout");
- errorclose(generator);
-}
-
-static void on_read(h2o_socket_t *sock, const char *err)
-{
- struct st_fcgi_generator_t *generator = sock->data;
- int can_keepalive = 0;
-
- if (err != NULL) {
- /* note: FastCGI server is allowed to close the connection any time after sending an empty FCGI_STDOUT record */
- if (!generator->sent_headers)
- h2o_req_log_error(generator->req, MODULE_NAME, "fastcgi connection closed unexpectedly");
- errorclose(generator);
- return;
- }
-
- /* handle the records */
- while (1) {
- struct st_fcgi_record_header_t header;
- size_t recsize;
- if (sock->input->size < FCGI_RECORD_HEADER_SIZE)
- break;
- decode_header(&header, sock->input->bytes);
- recsize = FCGI_RECORD_HEADER_SIZE + header.contentLength + header.paddingLength;
- if (sock->input->size < recsize)
- break;
- /* we have a complete record */
- switch (header.type) {
- case FCGI_STDOUT:
- if (handle_stdin_record(generator, &header) != 0)
- goto Error;
- h2o_buffer_consume(&sock->input, recsize);
- break;
- case FCGI_STDERR:
- if (header.contentLength != 0)
- h2o_req_log_error(generator->req, MODULE_NAME, "%.*s", (int)header.contentLength,
- sock->input->bytes + FCGI_RECORD_HEADER_SIZE);
- h2o_buffer_consume(&sock->input, recsize);
- break;
- case FCGI_END_REQUEST:
- if (!generator->sent_headers) {
- h2o_req_log_error(generator->req, MODULE_NAME, "received FCGI_END_REQUEST before end of the headers");
- goto Error;
- }
- h2o_buffer_consume(&sock->input, recsize);
- can_keepalive = 1;
- goto EOS_Received;
- default:
- h2o_req_log_error(generator->req, MODULE_NAME, "received unexpected record, type: %u", header.type);
- h2o_buffer_consume(&sock->input, recsize);
- if (!generator->sent_headers)
- goto Error;
- goto EOS_Received;
- }
- }
-
- /* send data if necessary */
- if (generator->sent_headers && generator->resp.sending.bytes_inflight == 0)
- do_send(generator);
-
- set_timeout(generator, &generator->ctx->io_timeout, on_rw_timeout);
- return;
-
-EOS_Received:
- send_eos_and_close(generator, can_keepalive);
- return;
-
-Error:
- errorclose(generator);
-}
-
-static void on_send_complete(h2o_socket_t *sock, const char *err)
-{
- struct st_fcgi_generator_t *generator = sock->data;
-
- set_timeout(generator, &generator->ctx->io_timeout, on_rw_timeout);
- /* do nothing else! all the rest is handled by the on_read */
-}
-
-static void on_connect(h2o_socket_t *sock, const char *errstr, void *data)
-{
- struct st_fcgi_generator_t *generator = data;
- iovec_vector_t vecs;
-
- generator->connect_req = NULL;
-
- if (sock == NULL) {
- h2o_req_log_error(generator->req, MODULE_NAME, "connection failed:%s", errstr);
- errorclose(generator);
- return;
- }
-
- generator->sock = sock;
- sock->data = generator;
-
- build_request(generator->req, &vecs, 1, 65535, &generator->ctx->handler->config);
-
- /* start sending the response */
- h2o_socket_write(generator->sock, vecs.entries, vecs.size, on_send_complete);
-
- set_timeout(generator, &generator->ctx->io_timeout, on_rw_timeout);
-
- /* activate the receiver; note: FCGI spec allows the app to start sending the response before it receives FCGI_STDIN */
- h2o_socket_read_start(sock, on_read);
-}
-
-static void do_proceed(h2o_generator_t *_generator, h2o_req_t *req)
-{
- struct st_fcgi_generator_t *generator = (void *)_generator;
-
- h2o_doublebuffer_consume(&generator->resp.sending);
- do_send(generator);
-}
-
-static void do_stop(h2o_generator_t *_generator, h2o_req_t *req)
-{
- struct st_fcgi_generator_t *generator = (void *)_generator;
- close_generator(generator);
-}
-
-static void on_connect_timeout(h2o_timeout_entry_t *entry)
-{
- struct st_fcgi_generator_t *generator = H2O_STRUCT_FROM_MEMBER(struct st_fcgi_generator_t, timeout, entry);
-
- h2o_req_log_error(generator->req, MODULE_NAME, "connect timeout");
- errorclose(generator);
-}
-
-static int on_req(h2o_handler_t *_handler, h2o_req_t *req)
-{
- h2o_fastcgi_handler_t *handler = (void *)_handler;
- struct st_fcgi_generator_t *generator;
-
- generator = h2o_mem_alloc_shared(&req->pool, sizeof(*generator), (void (*)(void *))close_generator);
- generator->super.proceed = do_proceed;
- generator->super.stop = do_stop;
- generator->ctx = h2o_context_get_handler_context(req->conn->ctx, &handler->super);
- generator->req = req;
- generator->sock = NULL;
- generator->sent_headers = 0;
- h2o_doublebuffer_init(&generator->resp.sending, &h2o_socket_buffer_prototype);
- h2o_buffer_init(&generator->resp.receiving, &h2o_socket_buffer_prototype);
- generator->timeout = (h2o_timeout_entry_t){0};
-
- set_timeout(generator, &generator->ctx->io_timeout, on_connect_timeout);
- h2o_socketpool_connect(&generator->connect_req, &handler->sockpool, req->conn->ctx->loop,
- &req->conn->ctx->receivers.hostinfo_getaddr, on_connect, generator);
-
- return 0;
-}
-
-static void on_context_init(h2o_handler_t *_handler, h2o_context_t *ctx)
-{
- h2o_fastcgi_handler_t *handler = (void *)_handler;
- struct st_fcgi_context_t *handler_ctx = h2o_mem_alloc(sizeof(*handler_ctx));
-
- /* use the first event loop for handling timeouts of the socket pool */
- if (handler->sockpool.timeout == UINT64_MAX)
- h2o_socketpool_set_timeout(&handler->sockpool, ctx->loop,
- handler->config.keepalive_timeout != 0 ? handler->config.keepalive_timeout : 60000);
-
- handler_ctx->handler = handler;
- h2o_timeout_init(ctx->loop, &handler_ctx->io_timeout, handler->config.io_timeout);
-
- h2o_context_set_handler_context(ctx, &handler->super, handler_ctx);
-}
-
-static void on_context_dispose(h2o_handler_t *_handler, h2o_context_t *ctx)
-{
- h2o_fastcgi_handler_t *handler = (void *)_handler;
- struct st_fcgi_context_t *handler_ctx = h2o_context_get_handler_context(ctx, &handler->super);
-
- if (handler_ctx == NULL)
- return;
-
- h2o_timeout_dispose(ctx->loop, &handler_ctx->io_timeout);
- free(handler_ctx);
-}
-
-static void on_handler_dispose(h2o_handler_t *_handler)
-{
- h2o_fastcgi_handler_t *handler = (void *)_handler;
-
- if (handler->config.callbacks.dispose != NULL)
- handler->config.callbacks.dispose(handler, handler->config.callbacks.data);
-
- h2o_socketpool_dispose(&handler->sockpool);
- free(handler->config.document_root.base);
-}
-
-static h2o_fastcgi_handler_t *register_common(h2o_pathconf_t *pathconf, h2o_fastcgi_config_vars_t *vars)
-{
- h2o_fastcgi_handler_t *handler = (void *)h2o_create_handler(pathconf, sizeof(*handler));
-
- handler->super.on_context_init = on_context_init;
- handler->super.on_context_dispose = on_context_dispose;
- handler->super.dispose = on_handler_dispose;
- handler->super.on_req = on_req;
- handler->config = *vars;
- if (vars->document_root.base != NULL)
- handler->config.document_root = h2o_strdup(NULL, vars->document_root.base, vars->document_root.len);
-
- return handler;
-}
-
-h2o_fastcgi_handler_t *h2o_fastcgi_register_by_hostport(h2o_pathconf_t *pathconf, const char *host, uint16_t port,
- h2o_fastcgi_config_vars_t *vars)
-{
- h2o_fastcgi_handler_t *handler = register_common(pathconf, vars);
-
- h2o_socketpool_init_by_hostport(&handler->sockpool, h2o_iovec_init(host, strlen(host)), port, 0, SIZE_MAX /* FIXME */);
- return handler;
-}
-
-h2o_fastcgi_handler_t *h2o_fastcgi_register_by_address(h2o_pathconf_t *pathconf, struct sockaddr *sa, socklen_t salen,
- h2o_fastcgi_config_vars_t *vars)
-{
- h2o_fastcgi_handler_t *handler = register_common(pathconf, vars);
-
- h2o_socketpool_init_by_address(&handler->sockpool, sa, salen, 0, SIZE_MAX /* FIXME */);
- return handler;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/file.c b/web/server/h2o/libh2o/lib/handler/file.c
deleted file mode 100644
index 5d7c7a2a4..000000000
--- a/web/server/h2o/libh2o/lib/handler/file.c
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Domingo Alvarez Duarte,
- * Tatsuhiko Kubo, Nick Desaulniers, Marc Hoersken,
- * Justin Zhu, Tatsuhiro Tsujikawa
- *
- * 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 <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "h2o.h"
-
-#define MAX_BUF_SIZE 65000
-#define BOUNDARY_SIZE 20
-#define FIXED_PART_SIZE (sizeof("\r\n--") - 1 + BOUNDARY_SIZE + sizeof("\r\nContent-Range: bytes=-/\r\nContent-Type: \r\n\r\n") - 1)
-
-struct st_h2o_sendfile_generator_t {
- h2o_generator_t super;
- struct {
- h2o_filecache_ref_t *ref;
- off_t off;
- } file;
- h2o_req_t *req;
- size_t bytesleft;
- h2o_iovec_t content_encoding;
- unsigned send_vary : 1;
- unsigned send_etag : 1;
- unsigned gunzip : 1;
- char *buf;
- struct {
- size_t filesize;
- size_t range_count;
- size_t *range_infos; /* size_t shows in pair. first is start offset, then length */
- h2o_iovec_t boundary; /* boundary used for multipart/byteranges */
- h2o_iovec_t mimetype; /* original mimetype for multipart */
- size_t current_range; /* range that processing now */
- } ranged;
- struct {
- char last_modified[H2O_TIMESTR_RFC1123_LEN + 1];
- char etag[H2O_FILECACHE_ETAG_MAXLEN + 1];
- } header_bufs;
-};
-
-struct st_h2o_file_handler_t {
- h2o_handler_t super;
- h2o_iovec_t conf_path; /* has "/" appended at last */
- h2o_iovec_t real_path; /* has "/" appended at last */
- h2o_mimemap_t *mimemap;
- int flags;
- size_t max_index_file_len;
- h2o_iovec_t index_files[1];
-};
-
-struct st_h2o_specific_file_handler_t {
- h2o_handler_t super;
- h2o_iovec_t real_path;
- h2o_mimemap_type_t *mime_type;
- int flags;
-};
-
-struct st_gzip_decompress_t {
- h2o_ostream_t super;
- h2o_compress_context_t *decompressor;
-};
-
-static const char *default_index_files[] = {"index.html", "index.htm", "index.txt", NULL};
-
-const char **h2o_file_default_index_files = default_index_files;
-
-#include "file/templates.c.h"
-
-static int tm_is_lessthan(struct tm *x, struct tm *y)
-{
-#define CMP(f) \
- if (x->f < y->f) \
- return 1; \
- else if (x->f > y->f) \
- return 0;
- CMP(tm_year);
- CMP(tm_mon);
- CMP(tm_mday);
- CMP(tm_hour);
- CMP(tm_min);
- CMP(tm_sec);
- return 0;
-#undef CMP
-}
-
-static void do_close(h2o_generator_t *_self, h2o_req_t *req)
-{
- struct st_h2o_sendfile_generator_t *self = (void *)_self;
- h2o_filecache_close_file(self->file.ref);
-}
-
-static void do_proceed(h2o_generator_t *_self, h2o_req_t *req)
-{
- struct st_h2o_sendfile_generator_t *self = (void *)_self;
- size_t rlen;
- ssize_t rret;
- h2o_iovec_t vec;
- h2o_send_state_t send_state;
-
- /* read the file */
- rlen = self->bytesleft;
- if (rlen > MAX_BUF_SIZE)
- rlen = MAX_BUF_SIZE;
- while ((rret = pread(self->file.ref->fd, self->buf, rlen, self->file.off)) == -1 && errno == EINTR)
- ;
- if (rret == -1) {
- h2o_send(req, NULL, 0, H2O_SEND_STATE_ERROR);
- do_close(&self->super, req);
- return;
- }
- self->file.off += rret;
- self->bytesleft -= rret;
- if (self->bytesleft == 0) {
- send_state = H2O_SEND_STATE_FINAL;
- } else {
- send_state = H2O_SEND_STATE_IN_PROGRESS;
- }
-
- /* send (and close if done) */
- vec.base = self->buf;
- vec.len = rret;
- h2o_send(req, &vec, 1, send_state);
- if (send_state == H2O_SEND_STATE_FINAL)
- do_close(&self->super, req);
-}
-
-static void do_multirange_proceed(h2o_generator_t *_self, h2o_req_t *req)
-{
- struct st_h2o_sendfile_generator_t *self = (void *)_self;
- size_t rlen, used_buf = 0;
- ssize_t rret, vecarrsize;
- h2o_iovec_t vec[2];
- h2o_send_state_t send_state;
-
- if (self->bytesleft == 0) {
- size_t *range_cur = self->ranged.range_infos + 2 * self->ranged.current_range;
- size_t range_end = *range_cur + *(range_cur + 1) - 1;
- if (H2O_LIKELY(self->ranged.current_range != 0))
- used_buf =
- sprintf(self->buf, "\r\n--%s\r\nContent-Type: %s\r\nContent-Range: bytes %zd-%zd/%zd\r\n\r\n",
- self->ranged.boundary.base, self->ranged.mimetype.base, *range_cur, range_end, self->ranged.filesize);
- else
- used_buf =
- sprintf(self->buf, "--%s\r\nContent-Type: %s\r\nContent-Range: bytes %zd-%zd/%zd\r\n\r\n",
- self->ranged.boundary.base, self->ranged.mimetype.base, *range_cur, range_end, self->ranged.filesize);
- self->ranged.current_range++;
- self->file.off = *range_cur;
- self->bytesleft = *++range_cur;
- }
- rlen = self->bytesleft;
- if (rlen + used_buf > MAX_BUF_SIZE)
- rlen = MAX_BUF_SIZE - used_buf;
- while ((rret = pread(self->file.ref->fd, self->buf + used_buf, rlen, self->file.off)) == -1 && errno == EINTR)
- ;
- if (rret == -1)
- goto Error;
- self->file.off += rret;
- self->bytesleft -= rret;
-
- vec[0].base = self->buf;
- vec[0].len = rret + used_buf;
- if (self->ranged.current_range == self->ranged.range_count && self->bytesleft == 0) {
- vec[1].base = h2o_mem_alloc_pool(&req->pool, sizeof("\r\n--") - 1 + BOUNDARY_SIZE + sizeof("--\r\n"));
- vec[1].len = sprintf(vec[1].base, "\r\n--%s--\r\n", self->ranged.boundary.base);
- vecarrsize = 2;
- send_state = H2O_SEND_STATE_FINAL;
- } else {
- vecarrsize = 1;
- send_state = H2O_SEND_STATE_IN_PROGRESS;
- }
- h2o_send(req, vec, vecarrsize, send_state);
- if (send_state == H2O_SEND_STATE_FINAL)
- do_close(&self->super, req);
- return;
-
-Error:
- h2o_send(req, NULL, 0, H2O_SEND_STATE_ERROR);
- do_close(&self->super, req);
- return;
-}
-
-static h2o_send_state_t do_pull(h2o_generator_t *_self, h2o_req_t *req, h2o_iovec_t *buf)
-{
- struct st_h2o_sendfile_generator_t *self = (void *)_self;
- ssize_t rret;
-
- if (self->bytesleft < buf->len)
- buf->len = self->bytesleft;
- while ((rret = pread(self->file.ref->fd, buf->base, buf->len, self->file.off)) == -1 && errno == EINTR)
- ;
- if (rret <= 0) {
- buf->len = 0;
- self->bytesleft = 0;
- do_close(&self->super, req);
- return H2O_SEND_STATE_ERROR;
- } else {
- buf->len = rret;
- self->file.off += rret;
- self->bytesleft -= rret;
- }
-
- if (self->bytesleft != 0)
- return H2O_SEND_STATE_IN_PROGRESS;
- do_close(&self->super, req);
- return H2O_SEND_STATE_FINAL;
-}
-
-static struct st_h2o_sendfile_generator_t *create_generator(h2o_req_t *req, const char *path, size_t path_len, int *is_dir,
- int flags)
-{
- struct st_h2o_sendfile_generator_t *self;
- h2o_filecache_ref_t *fileref;
- h2o_iovec_t content_encoding = (h2o_iovec_t){NULL};
- unsigned gunzip = 0;
-
- *is_dir = 0;
-
- if ((flags & H2O_FILE_FLAG_SEND_COMPRESSED) != 0 && req->version >= 0x101) {
- int compressible_types = h2o_get_compressible_types(&req->headers);
- if (compressible_types != 0) {
- char *variant_path = h2o_mem_alloc_pool(&req->pool, path_len + sizeof(".gz"));
- memcpy(variant_path, path, path_len);
-#define TRY_VARIANT(mask, enc, ext) \
- if ((compressible_types & mask) != 0) { \
- strcpy(variant_path + path_len, ext); \
- if ((fileref = h2o_filecache_open_file(req->conn->ctx->filecache, variant_path, O_RDONLY | O_CLOEXEC)) != NULL) { \
- content_encoding = h2o_iovec_init(enc, sizeof(enc) - 1); \
- goto Opened; \
- } \
- }
- TRY_VARIANT(H2O_COMPRESSIBLE_BROTLI, "br", ".br");
- TRY_VARIANT(H2O_COMPRESSIBLE_GZIP, "gzip", ".gz");
-#undef TRY_VARIANT
- }
- }
- if ((fileref = h2o_filecache_open_file(req->conn->ctx->filecache, path, O_RDONLY | O_CLOEXEC)) != NULL) {
- goto Opened;
- }
- if ((flags & H2O_FILE_FLAG_GUNZIP) != 0 && req->version >= 0x101) {
- char *variant_path = h2o_mem_alloc_pool(&req->pool, path_len + sizeof(".gz"));
- memcpy(variant_path, path, path_len);
- strcpy(variant_path + path_len, ".gz");
- if ((fileref = h2o_filecache_open_file(req->conn->ctx->filecache, variant_path, O_RDONLY | O_CLOEXEC)) != NULL) {
- gunzip = 1;
- goto Opened;
- }
- }
- return NULL;
-
-Opened:
- if (S_ISDIR(fileref->st.st_mode)) {
- h2o_filecache_close_file(fileref);
- *is_dir = 1;
- return NULL;
- }
-
- self = h2o_mem_alloc_pool(&req->pool, sizeof(*self));
- self->super.proceed = do_proceed;
- self->super.stop = do_close;
- self->file.ref = fileref;
- self->file.off = 0;
- self->req = NULL;
- self->bytesleft = self->file.ref->st.st_size;
- self->ranged.range_count = 0;
- self->ranged.range_infos = NULL;
- self->content_encoding = content_encoding;
- self->send_vary = (flags & H2O_FILE_FLAG_SEND_COMPRESSED) != 0;
- self->send_etag = (flags & H2O_FILE_FLAG_NO_ETAG) == 0;
- self->gunzip = gunzip;
-
- return self;
-}
-
-static void add_headers_unconditional(struct st_h2o_sendfile_generator_t *self, h2o_req_t *req)
-{
- /* RFC 7232 4.1: The server generating a 304 response MUST generate any of the following header fields that would have been sent
- * in a 200 (OK) response to the same request: Cache-Control, Content-Location, Date, ETag, Expires, and Vary (snip) a sender
- * SHOULD NOT generate representation metadata other than the above listed fields unless said metadata exists for the purpose of
- * guiding cache updates. */
- if (self->send_etag) {
- size_t etag_len = h2o_filecache_get_etag(self->file.ref, self->header_bufs.etag);
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_ETAG, NULL, self->header_bufs.etag, etag_len);
- }
- if (self->send_vary)
- h2o_set_header_token(&req->pool, &req->res.headers, H2O_TOKEN_VARY, H2O_STRLIT("accept-encoding"));
-}
-
-static void send_decompressed(h2o_ostream_t *_self, h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state)
-{
- struct st_gzip_decompress_t *self = (void *)_self;
- h2o_iovec_t *outbufs;
- size_t outbufcnt;
-
- self->decompressor->transform(self->decompressor, inbufs, inbufcnt, state, &outbufs, &outbufcnt);
- h2o_ostream_send_next(&self->super, req, outbufs, outbufcnt, state);
-}
-
-static void do_send_file(struct st_h2o_sendfile_generator_t *self, h2o_req_t *req, int status, const char *reason,
- h2o_iovec_t mime_type, h2o_mime_attributes_t *mime_attr, int is_get)
-{
- /* link the request */
- self->req = req;
-
- /* setup response */
- req->res.status = status;
- req->res.reason = reason;
- req->res.content_length = self->gunzip ? SIZE_MAX : self->bytesleft;
- req->res.mime_attr = mime_attr;
-
- if (self->ranged.range_count > 1) {
- mime_type.base = h2o_mem_alloc_pool(&req->pool, 52);
- mime_type.len = sprintf(mime_type.base, "multipart/byteranges; boundary=%s", self->ranged.boundary.base);
- }
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, NULL, mime_type.base, mime_type.len);
- h2o_filecache_get_last_modified(self->file.ref, self->header_bufs.last_modified);
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_LAST_MODIFIED, NULL, self->header_bufs.last_modified,
- H2O_TIMESTR_RFC1123_LEN);
- add_headers_unconditional(self, req);
- if (self->content_encoding.base != NULL)
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_ENCODING, NULL, self->content_encoding.base,
- self->content_encoding.len);
- if (self->ranged.range_count == 0)
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_ACCEPT_RANGES, NULL, H2O_STRLIT("bytes"));
- else if (self->ranged.range_count == 1) {
- h2o_iovec_t content_range;
- content_range.base = h2o_mem_alloc_pool(&req->pool, 128);
- content_range.len = sprintf(content_range.base, "bytes %zd-%zd/%zd", self->ranged.range_infos[0],
- self->ranged.range_infos[0] + self->ranged.range_infos[1] - 1, self->ranged.filesize);
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_RANGE, NULL, content_range.base, content_range.len);
- }
-
- /* special path for cases where we do not need to send any data */
- if (!is_get || self->bytesleft == 0) {
- static h2o_generator_t generator = {NULL, NULL};
- h2o_start_response(req, &generator);
- h2o_send(req, NULL, 0, H2O_SEND_STATE_FINAL);
- do_close(&self->super, req);
- return;
- }
-
- /* send data */
- h2o_start_response(req, &self->super);
-
- /* dynamically setup gzip decompress ostream */
- if (self->gunzip) {
- struct st_gzip_decompress_t *decoder = (void *)h2o_add_ostream(req, sizeof(struct st_gzip_decompress_t), &req->_ostr_top);
- decoder->decompressor = h2o_compress_gunzip_open(&req->pool);
- decoder->super.do_send = send_decompressed;
- }
-
- if (self->ranged.range_count == 1)
- self->file.off = self->ranged.range_infos[0];
- if (req->_ostr_top->start_pull != NULL && self->ranged.range_count < 2) {
- req->_ostr_top->start_pull(req->_ostr_top, do_pull);
- } else {
- size_t bufsz = MAX_BUF_SIZE;
- if (self->bytesleft < bufsz)
- bufsz = self->bytesleft;
- self->buf = h2o_mem_alloc_pool(&req->pool, bufsz);
- if (self->ranged.range_count < 2)
- do_proceed(&self->super, req);
- else {
- self->bytesleft = 0;
- self->super.proceed = do_multirange_proceed;
- do_multirange_proceed(&self->super, req);
- }
- }
-}
-
-int h2o_file_send(h2o_req_t *req, int status, const char *reason, const char *path, h2o_iovec_t mime_type, int flags)
-{
- struct st_h2o_sendfile_generator_t *self;
- int is_dir;
-
- if ((self = create_generator(req, path, strlen(path), &is_dir, flags)) == NULL)
- return -1;
- /* note: is_dir is not handled */
- do_send_file(self, req, status, reason, mime_type, NULL, 1);
- return 0;
-}
-
-static int send_dir_listing(h2o_req_t *req, const char *path, size_t path_len, int is_get)
-{
- static h2o_generator_t generator = {NULL, NULL};
- DIR *dp;
- h2o_buffer_t *body;
- h2o_iovec_t bodyvec;
-
- /* build html */
- if ((dp = opendir(path)) == NULL)
- return -1;
- body = build_dir_listing_html(&req->pool, req->path_normalized, dp);
- closedir(dp);
-
- bodyvec = h2o_iovec_init(body->bytes, body->size);
- h2o_buffer_link_to_pool(body, &req->pool);
-
- /* send response */
- req->res.status = 200;
- req->res.reason = "OK";
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, NULL, H2O_STRLIT("text/html; charset=utf-8"));
-
- /* send headers */
- if (!is_get) {
- h2o_send_inline(req, NULL, 0);
- return 0;
- }
-
- /* send data */
- h2o_start_response(req, &generator);
- h2o_send(req, &bodyvec, 1, H2O_SEND_STATE_FINAL);
- return 0;
-}
-
-static size_t *process_range(h2o_mem_pool_t *pool, h2o_iovec_t *range_value, size_t file_size, size_t *ret)
-{
-#define CHECK_EOF() \
- if (buf == buf_end) \
- return NULL;
-
-#define CHECK_OVERFLOW(range) \
- if (range == SIZE_MAX) \
- return NULL;
-
- size_t range_start = SIZE_MAX, range_count = 0;
- char *buf = range_value->base, *buf_end = buf + range_value->len;
- int needs_comma = 0;
- H2O_VECTOR(size_t) ranges = {NULL};
-
- if (range_value->len < 6 || memcmp(buf, "bytes=", 6) != 0)
- return NULL;
-
- buf += 6;
- CHECK_EOF();
-
- /* most range requests contain only one range */
- do {
- while (1) {
- if (*buf != ',') {
- if (needs_comma)
- return NULL;
- break;
- }
- needs_comma = 0;
- buf++;
- while (H2O_UNLIKELY(*buf == ' ') || H2O_UNLIKELY(*buf == '\t')) {
- buf++;
- CHECK_EOF();
- }
- }
- if (H2O_UNLIKELY(buf == buf_end))
- break;
- if (H2O_LIKELY((range_start = h2o_strtosizefwd(&buf, buf_end - buf)) != SIZE_MAX)) {
- CHECK_EOF();
- if (*buf++ != '-')
- return NULL;
- range_count = h2o_strtosizefwd(&buf, buf_end - buf);
- if (H2O_UNLIKELY(range_start >= file_size)) {
- range_start = SIZE_MAX;
- } else if (H2O_LIKELY(range_count != SIZE_MAX)) {
- if (H2O_UNLIKELY(range_count > file_size - 1))
- range_count = file_size - 1;
- if (H2O_LIKELY(range_start <= range_count))
- range_count -= range_start - 1;
- else
- range_start = SIZE_MAX;
- } else {
- range_count = file_size - range_start;
- }
- } else if (H2O_LIKELY(*buf++ == '-')) {
- CHECK_EOF();
- range_count = h2o_strtosizefwd(&buf, buf_end - buf);
- if (H2O_UNLIKELY(range_count == SIZE_MAX))
- return NULL;
- if (H2O_LIKELY(range_count != 0)) {
- if (H2O_UNLIKELY(range_count > file_size))
- range_count = file_size;
- range_start = file_size - range_count;
- } else {
- range_start = SIZE_MAX;
- }
- } else {
- return NULL;
- }
-
- if (H2O_LIKELY(range_start != SIZE_MAX)) {
- h2o_vector_reserve(pool, &ranges, ranges.size + 2);
- ranges.entries[ranges.size++] = range_start;
- ranges.entries[ranges.size++] = range_count;
- }
- if (buf != buf_end)
- while (H2O_UNLIKELY(*buf == ' ') || H2O_UNLIKELY(*buf == '\t')) {
- buf++;
- CHECK_EOF();
- }
- needs_comma = 1;
- } while (H2O_UNLIKELY(buf < buf_end));
- *ret = ranges.size / 2;
- return ranges.entries;
-#undef CHECK_EOF
-#undef CHECK_OVERFLOW
-}
-
-static void gen_rand_string(h2o_iovec_t *s)
-{
- int i;
- static const char alphanum[] = "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz";
-
- for (i = 0; i < s->len; ++i) {
- s->base[i] = alphanum[h2o_rand() % (sizeof(alphanum) - 1)];
- }
-
- s->base[s->len] = 0;
-}
-
-static int delegate_dynamic_request(h2o_req_t *req, h2o_iovec_t script_name, h2o_iovec_t path_info, const char *local_path,
- size_t local_path_len, h2o_mimemap_type_t *mime_type)
-{
- h2o_filereq_t *filereq;
- h2o_handler_t *handler;
-
- assert(mime_type->data.dynamic.pathconf.handlers.size == 1);
-
- filereq = h2o_mem_alloc_pool(&req->pool, sizeof(*filereq));
- filereq->script_name = script_name;
- filereq->path_info = path_info;
- filereq->local_path = h2o_strdup(&req->pool, local_path, local_path_len);
-
- h2o_req_bind_conf(req, req->hostconf, &mime_type->data.dynamic.pathconf);
- req->filereq = filereq;
-
- handler = mime_type->data.dynamic.pathconf.handlers.entries[0];
- return handler->on_req(handler, req);
-}
-
-static int try_dynamic_request(h2o_file_handler_t *self, h2o_req_t *req, char *rpath, size_t rpath_len)
-{
- /* we have full local path in {rpath,rpath_len}, and need to split it into name and path_info */
- struct stat st;
- size_t slash_at = self->real_path.len;
-
- while (1) {
- /* find the next slash (or return -1 if failed) */
- for (++slash_at;; ++slash_at) {
- if (slash_at >= rpath_len)
- return -1;
- if (rpath[slash_at] == '/')
- break;
- }
- /* change the slash to '\0', and check if the file exists */
- rpath[slash_at] = '\0';
- if (stat(rpath, &st) != 0)
- return -1;
- if (!S_ISDIR(st.st_mode))
- break;
- /* restore slash, and continue the search */
- rpath[slash_at] = '/';
- }
-
- /* file found! */
- h2o_mimemap_type_t *mime_type = h2o_mimemap_get_type_by_extension(self->mimemap, h2o_get_filext(rpath, slash_at));
- switch (mime_type->type) {
- case H2O_MIMEMAP_TYPE_MIMETYPE:
- return -1;
- case H2O_MIMEMAP_TYPE_DYNAMIC: {
- h2o_iovec_t script_name = h2o_iovec_init(req->path_normalized.base, self->conf_path.len + slash_at - self->real_path.len);
- h2o_iovec_t path_info =
- h2o_iovec_init(req->path_normalized.base + script_name.len, req->path_normalized.len - script_name.len);
- return delegate_dynamic_request(req, script_name, path_info, rpath, slash_at, mime_type);
- }
- }
- fprintf(stderr, "unknown h2o_miemmap_type_t::type (%d)\n", (int)mime_type->type);
- abort();
-}
-
-static void send_method_not_allowed(h2o_req_t *req)
-{
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_ALLOW, NULL, H2O_STRLIT("GET, HEAD"));
- h2o_send_error_405(req, "Method Not Allowed", "method not allowed", H2O_SEND_ERROR_KEEP_HEADERS);
-}
-
-static int serve_with_generator(struct st_h2o_sendfile_generator_t *generator, h2o_req_t *req, h2o_iovec_t resolved_path,
- const char *rpath, size_t rpath_len, h2o_mimemap_type_t *mime_type)
-{
- enum { METHOD_IS_GET, METHOD_IS_HEAD, METHOD_IS_OTHER } method_type;
- size_t if_modified_since_header_index, if_none_match_header_index;
- size_t range_header_index;
-
- /* determine the method */
- if (h2o_memis(req->method.base, req->method.len, H2O_STRLIT("GET"))) {
- method_type = METHOD_IS_GET;
- } else if (h2o_memis(req->method.base, req->method.len, H2O_STRLIT("HEAD"))) {
- method_type = METHOD_IS_HEAD;
- } else {
- method_type = METHOD_IS_OTHER;
- }
-
- /* obtain mime type */
- if (mime_type->type == H2O_MIMEMAP_TYPE_DYNAMIC) {
- do_close(&generator->super, req);
- return delegate_dynamic_request(req, resolved_path, h2o_iovec_init(NULL, 0), rpath, rpath_len, mime_type);
- }
- assert(mime_type->type == H2O_MIMEMAP_TYPE_MIMETYPE);
-
- /* if-non-match and if-modified-since */
- if ((if_none_match_header_index = h2o_find_header(&req->headers, H2O_TOKEN_IF_NONE_MATCH, SIZE_MAX)) != -1) {
- h2o_iovec_t *if_none_match = &req->headers.entries[if_none_match_header_index].value;
- char etag[H2O_FILECACHE_ETAG_MAXLEN + 1];
- size_t etag_len = h2o_filecache_get_etag(generator->file.ref, etag);
- if (h2o_memis(if_none_match->base, if_none_match->len, etag, etag_len))
- goto NotModified;
- } else if ((if_modified_since_header_index = h2o_find_header(&req->headers, H2O_TOKEN_IF_MODIFIED_SINCE, SIZE_MAX)) != -1) {
- h2o_iovec_t *ims_vec = &req->headers.entries[if_modified_since_header_index].value;
- struct tm ims_tm, *last_modified_tm;
- if (h2o_time_parse_rfc1123(ims_vec->base, ims_vec->len, &ims_tm) == 0) {
- last_modified_tm = h2o_filecache_get_last_modified(generator->file.ref, NULL);
- if (!tm_is_lessthan(&ims_tm, last_modified_tm))
- goto NotModified;
- }
- }
-
- /* only allow GET or POST for static files */
- if (method_type == METHOD_IS_OTHER) {
- do_close(&generator->super, req);
- send_method_not_allowed(req);
- return 0;
- }
-
- /* if-range */
- if ((range_header_index = h2o_find_header(&req->headers, H2O_TOKEN_RANGE, SIZE_MAX)) != -1) {
- h2o_iovec_t *range = &req->headers.entries[range_header_index].value;
- size_t *range_infos, range_count;
- range_infos = process_range(&req->pool, range, generator->bytesleft, &range_count);
- if (range_infos == NULL) {
- h2o_iovec_t content_range;
- content_range.base = h2o_mem_alloc_pool(&req->pool, 32);
- content_range.len = sprintf(content_range.base, "bytes */%zu", generator->bytesleft);
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_RANGE, NULL, content_range.base, content_range.len);
- h2o_send_error_416(req, "Request Range Not Satisfiable", "requested range not satisfiable",
- H2O_SEND_ERROR_KEEP_HEADERS);
- goto Close;
- }
- generator->ranged.range_count = range_count;
- generator->ranged.range_infos = range_infos;
- generator->ranged.current_range = 0;
- generator->ranged.filesize = generator->bytesleft;
-
- /* set content-length according to range */
- if (range_count == 1)
- generator->bytesleft = range_infos[1];
- else {
- generator->ranged.mimetype = h2o_strdup(&req->pool, mime_type->data.mimetype.base, mime_type->data.mimetype.len);
- size_t final_content_len = 0, size_tmp = 0, size_fixed_each_part, i;
- generator->ranged.boundary.base = h2o_mem_alloc_pool(&req->pool, BOUNDARY_SIZE + 1);
- generator->ranged.boundary.len = BOUNDARY_SIZE;
- gen_rand_string(&generator->ranged.boundary);
- i = generator->bytesleft;
- while (i) {
- i /= 10;
- size_tmp++;
- }
- size_fixed_each_part = FIXED_PART_SIZE + mime_type->data.mimetype.len + size_tmp;
- for (i = 0; i < range_count; i++) {
- size_tmp = *range_infos++;
- if (size_tmp == 0)
- final_content_len++;
- while (size_tmp) {
- size_tmp /= 10;
- final_content_len++;
- }
-
- size_tmp = *(range_infos - 1);
- final_content_len += *range_infos;
-
- size_tmp += *range_infos++ - 1;
- if (size_tmp == 0)
- final_content_len++;
- while (size_tmp) {
- size_tmp /= 10;
- final_content_len++;
- }
- }
- final_content_len += sizeof("\r\n--") - 1 + BOUNDARY_SIZE + sizeof("--\r\n") - 1 + size_fixed_each_part * range_count -
- (sizeof("\r\n") - 1);
- generator->bytesleft = final_content_len;
- }
- do_send_file(generator, req, 206, "Partial Content", mime_type->data.mimetype, &h2o_mime_attributes_as_is,
- method_type == METHOD_IS_GET);
- return 0;
- }
-
- /* return file */
- do_send_file(generator, req, 200, "OK", mime_type->data.mimetype, &mime_type->data.attr, method_type == METHOD_IS_GET);
- return 0;
-
-NotModified:
- req->res.status = 304;
- req->res.reason = "Not Modified";
- add_headers_unconditional(generator, req);
- h2o_send_inline(req, NULL, 0);
-Close:
- do_close(&generator->super, req);
- return 0;
-}
-
-static int on_req(h2o_handler_t *_self, h2o_req_t *req)
-{
- h2o_file_handler_t *self = (void *)_self;
- char *rpath;
- size_t rpath_len, req_path_prefix;
- struct st_h2o_sendfile_generator_t *generator = NULL;
- int is_dir;
-
- if (req->path_normalized.len < self->conf_path.len) {
- h2o_iovec_t dest = h2o_uri_escape(&req->pool, self->conf_path.base, self->conf_path.len, "/");
- if (req->query_at != SIZE_MAX)
- dest = h2o_concat(&req->pool, dest, h2o_iovec_init(req->path.base + req->query_at, req->path.len - req->query_at));
- h2o_send_redirect(req, 301, "Moved Permanently", dest.base, dest.len);
- return 0;
- }
-
- /* build path (still unterminated at the end of the block) */
- req_path_prefix = self->conf_path.len;
- rpath = alloca(self->real_path.len + (req->path_normalized.len - req_path_prefix) + self->max_index_file_len + 1);
- rpath_len = 0;
- memcpy(rpath + rpath_len, self->real_path.base, self->real_path.len);
- rpath_len += self->real_path.len;
- memcpy(rpath + rpath_len, req->path_normalized.base + req_path_prefix, req->path_normalized.len - req_path_prefix);
- rpath_len += req->path_normalized.len - req_path_prefix;
-
- h2o_iovec_t resolved_path = req->path_normalized;
-
- /* build generator (as well as terminating the rpath and its length upon success) */
- if (rpath[rpath_len - 1] == '/') {
- h2o_iovec_t *index_file;
- for (index_file = self->index_files; index_file->base != NULL; ++index_file) {
- memcpy(rpath + rpath_len, index_file->base, index_file->len);
- rpath[rpath_len + index_file->len] = '\0';
- if ((generator = create_generator(req, rpath, rpath_len + index_file->len, &is_dir, self->flags)) != NULL) {
- rpath_len += index_file->len;
- resolved_path = h2o_concat(&req->pool, req->path_normalized, *index_file);
- goto Opened;
- }
- if (is_dir) {
- /* note: apache redirects "path/" to "path/index.txt/" if index.txt is a dir */
- h2o_iovec_t dest = h2o_concat(&req->pool, req->path_normalized, *index_file, h2o_iovec_init(H2O_STRLIT("/")));
- dest = h2o_uri_escape(&req->pool, dest.base, dest.len, "/");
- if (req->query_at != SIZE_MAX)
- dest =
- h2o_concat(&req->pool, dest, h2o_iovec_init(req->path.base + req->query_at, req->path.len - req->query_at));
- h2o_send_redirect(req, 301, "Moved Permantently", dest.base, dest.len);
- return 0;
- }
- if (errno != ENOENT)
- break;
- }
- if (index_file->base == NULL && (self->flags & H2O_FILE_FLAG_DIR_LISTING) != 0) {
- rpath[rpath_len] = '\0';
- int is_get = 0;
- if (h2o_memis(req->method.base, req->method.len, H2O_STRLIT("GET"))) {
- is_get = 1;
- } else if (h2o_memis(req->method.base, req->method.len, H2O_STRLIT("HEAD"))) {
- /* ok */
- } else {
- send_method_not_allowed(req);
- return 0;
- }
- if (send_dir_listing(req, rpath, rpath_len, is_get) == 0)
- return 0;
- }
- } else {
- rpath[rpath_len] = '\0';
- if ((generator = create_generator(req, rpath, rpath_len, &is_dir, self->flags)) != NULL)
- goto Opened;
- if (is_dir) {
- h2o_iovec_t dest = h2o_concat(&req->pool, req->path_normalized, h2o_iovec_init(H2O_STRLIT("/")));
- dest = h2o_uri_escape(&req->pool, dest.base, dest.len, "/");
- if (req->query_at != SIZE_MAX)
- dest = h2o_concat(&req->pool, dest, h2o_iovec_init(req->path.base + req->query_at, req->path.len - req->query_at));
- h2o_send_redirect(req, 301, "Moved Permanently", dest.base, dest.len);
- return 0;
- }
- }
- /* failed to open */
-
- if (errno == ENFILE || errno == EMFILE) {
- h2o_send_error_503(req, "Service Unavailable", "please try again later", 0);
- } else {
- if (h2o_mimemap_has_dynamic_type(self->mimemap) && try_dynamic_request(self, req, rpath, rpath_len) == 0)
- return 0;
- if (errno == ENOENT || errno == ENOTDIR) {
- return -1;
- } else {
- h2o_send_error_403(req, "Access Forbidden", "access forbidden", 0);
- }
- }
- return 0;
-
-Opened:
- return serve_with_generator(generator, req, resolved_path, rpath, rpath_len,
- h2o_mimemap_get_type_by_extension(self->mimemap, h2o_get_filext(rpath, rpath_len)));
-}
-
-static void on_context_init(h2o_handler_t *_self, h2o_context_t *ctx)
-{
- h2o_file_handler_t *self = (void *)_self;
-
- h2o_mimemap_on_context_init(self->mimemap, ctx);
-}
-
-static void on_context_dispose(h2o_handler_t *_self, h2o_context_t *ctx)
-{
- h2o_file_handler_t *self = (void *)_self;
-
- h2o_mimemap_on_context_dispose(self->mimemap, ctx);
-}
-
-static void on_dispose(h2o_handler_t *_self)
-{
- h2o_file_handler_t *self = (void *)_self;
- size_t i;
-
- free(self->conf_path.base);
- free(self->real_path.base);
- h2o_mem_release_shared(self->mimemap);
- for (i = 0; self->index_files[i].base != NULL; ++i)
- free(self->index_files[i].base);
-}
-
-h2o_file_handler_t *h2o_file_register(h2o_pathconf_t *pathconf, const char *real_path, const char **index_files,
- h2o_mimemap_t *mimemap, int flags)
-{
- h2o_file_handler_t *self;
- size_t i;
-
- if (index_files == NULL)
- index_files = default_index_files;
-
- /* allocate memory */
- for (i = 0; index_files[i] != NULL; ++i)
- ;
- self =
- (void *)h2o_create_handler(pathconf, offsetof(h2o_file_handler_t, index_files[0]) + sizeof(self->index_files[0]) * (i + 1));
-
- /* setup callbacks */
- self->super.on_context_init = on_context_init;
- self->super.on_context_dispose = on_context_dispose;
- self->super.dispose = on_dispose;
- self->super.on_req = on_req;
-
- /* setup attributes */
- self->conf_path = h2o_strdup_slashed(NULL, pathconf->path.base, pathconf->path.len);
- self->real_path = h2o_strdup_slashed(NULL, real_path, SIZE_MAX);
- if (mimemap != NULL) {
- h2o_mem_addref_shared(mimemap);
- self->mimemap = mimemap;
- } else {
- self->mimemap = h2o_mimemap_create();
- }
- self->flags = flags;
- for (i = 0; index_files[i] != NULL; ++i) {
- self->index_files[i] = h2o_strdup(NULL, index_files[i], SIZE_MAX);
- if (self->max_index_file_len < self->index_files[i].len)
- self->max_index_file_len = self->index_files[i].len;
- }
-
- return self;
-}
-
-h2o_mimemap_t *h2o_file_get_mimemap(h2o_file_handler_t *handler)
-{
- return handler->mimemap;
-}
-
-static void specific_handler_on_context_init(h2o_handler_t *_self, h2o_context_t *ctx)
-{
- struct st_h2o_specific_file_handler_t *self = (void *)_self;
-
- if (self->mime_type->type == H2O_MIMEMAP_TYPE_DYNAMIC)
- h2o_context_init_pathconf_context(ctx, &self->mime_type->data.dynamic.pathconf);
-}
-
-static void specific_handler_on_context_dispose(h2o_handler_t *_self, h2o_context_t *ctx)
-{
- struct st_h2o_specific_file_handler_t *self = (void *)_self;
-
- if (self->mime_type->type == H2O_MIMEMAP_TYPE_DYNAMIC)
- h2o_context_dispose_pathconf_context(ctx, &self->mime_type->data.dynamic.pathconf);
-}
-
-static void specific_handler_on_dispose(h2o_handler_t *_self)
-{
- struct st_h2o_specific_file_handler_t *self = (void *)_self;
-
- free(self->real_path.base);
- h2o_mem_release_shared(self->mime_type);
-}
-
-static int specific_handler_on_req(h2o_handler_t *_self, h2o_req_t *req)
-{
- struct st_h2o_specific_file_handler_t *self = (void *)_self;
- struct st_h2o_sendfile_generator_t *generator;
- int is_dir;
-
- /* open file (or send error or return -1) */
- if ((generator = create_generator(req, self->real_path.base, self->real_path.len, &is_dir, self->flags)) == NULL) {
- if (is_dir) {
- h2o_send_error_403(req, "Access Forbidden", "access forbidden", 0);
- } else if (errno == ENOENT) {
- return -1;
- } else if (errno == ENFILE || errno == EMFILE) {
- h2o_send_error_503(req, "Service Unavailable", "please try again later", 0);
- } else {
- h2o_send_error_403(req, "Access Forbidden", "access forbidden", 0);
- }
- return 0;
- }
-
- return serve_with_generator(generator, req, req->path_normalized, self->real_path.base, self->real_path.len, self->mime_type);
-}
-
-h2o_handler_t *h2o_file_register_file(h2o_pathconf_t *pathconf, const char *real_path, h2o_mimemap_type_t *mime_type, int flags)
-{
- struct st_h2o_specific_file_handler_t *self = (void *)h2o_create_handler(pathconf, sizeof(*self));
-
- self->super.on_context_init = specific_handler_on_context_init;
- self->super.on_context_dispose = specific_handler_on_context_dispose;
- self->super.dispose = specific_handler_on_dispose;
- self->super.on_req = specific_handler_on_req;
-
- self->real_path = h2o_strdup(NULL, real_path, SIZE_MAX);
- h2o_mem_addref_shared(mime_type);
- self->mime_type = mime_type;
- self->flags = flags;
-
- return &self->super;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/file/_templates.c.h b/web/server/h2o/libh2o/lib/handler/file/_templates.c.h
deleted file mode 100644
index 11b73577c..000000000
--- a/web/server/h2o/libh2o/lib/handler/file/_templates.c.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.
- *
- * lib/file/templates.c.h is automatically generated from lib/file/_templates.h
- * with command:
- * picotemplate.pl --conf=misc/picotemplate-conf.pl lib/file/_templates.c.h
- */
-
-#include <limits.h>
-
-static int cmpstrptr(const void *_x, const void *_y)
-{
- const char *x = *(const char **)_x;
- const char *y = *(const char **)_y;
- return strcmp(x, y);
-}
-
-#if !defined(NAME_MAX) || defined(__linux__)
-/* readdir(3) is known to be thread-safe on Linux and should be thread-safe on a platform that does not have a predefined value for
- NAME_MAX */
-#define FOREACH_DIRENT(dp, dent) \
- struct dirent *dent; \
- while ((dent = readdir(dp)) != NULL)
-#else
-#define FOREACH_DIRENT(dp, dent) \
- struct { \
- struct dirent d; \
- char s[NAME_MAX + 1]; \
- } dent_; \
- struct dirent *dentp, *dent = &dent_.d; \
- int ret; \
- while ((ret = readdir_r(dp, dent, &dentp)) == 0 && dentp != NULL)
-#endif /* FOREACH_DIRENT */
-
-static h2o_buffer_t *build_dir_listing_html(h2o_mem_pool_t *pool, h2o_iovec_t path_normalized, DIR* dp)
-{
- H2O_VECTOR(char *) files = {NULL};
-
- { /* build list of files */
- FOREACH_DIRENT(dp, dent)
- {
- if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
- continue;
- h2o_vector_reserve(pool, &files, files.size + 1);
- files.entries[files.size++] = h2o_strdup(pool, dent->d_name, SIZE_MAX).base;
- }
- if (files.size > 1)
- qsort(files.entries, files.size, sizeof(files.entries[0]), cmpstrptr);
- }
-
- h2o_buffer_t *_;
- h2o_iovec_t path_normalized_escaped = h2o_htmlescape(pool, path_normalized.base, path_normalized.len);
-
- h2o_buffer_init(&_, &h2o_socket_buffer_prototype);
-
-?<!DOCTYPE html>
-?<TITLE>Index of <?= path_normalized_escaped ?></TITLE>
-?<H2>Index of <?= path_normalized_escaped ?></H2>
-?<UL>
-?<LI><A HREF="..">Parent Directory</A>
-
- size_t i;
- for (i = 0; i != files.size; ++i) {
- h2o_iovec_t link_escaped = h2o_uri_escape(pool, files.entries[i], strlen(files.entries[i]), NULL);
- link_escaped = h2o_htmlescape(pool, link_escaped.base, link_escaped.len);
- h2o_iovec_t label_escaped = h2o_htmlescape(pool, files.entries[i], strlen(files.entries[i]));
-?<LI><A HREF="<?= link_escaped ?>"><?= label_escaped ?></A>
- }
-?</UL>
-
- return _;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/file/templates.c.h b/web/server/h2o/libh2o/lib/handler/file/templates.c.h
deleted file mode 100644
index 24c12dae5..000000000
--- a/web/server/h2o/libh2o/lib/handler/file/templates.c.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.
- *
- * lib/file/templates.c.h is automatically generated from lib/file/_templates.h
- * with command:
- * picotemplate.pl --conf=misc/picotemplate-conf.pl lib/file/_templates.c.h
- */
-
-#include <limits.h>
-
-static int cmpstrptr(const void *_x, const void *_y)
-{
- const char *x = *(const char **)_x;
- const char *y = *(const char **)_y;
- return strcmp(x, y);
-}
-
-#if !defined(NAME_MAX) || defined(__linux__)
-/* readdir(3) is known to be thread-safe on Linux and should be thread-safe on a platform that does not have a predefined value for
- NAME_MAX */
-#define FOREACH_DIRENT(dp, dent) \
- struct dirent *dent; \
- while ((dent = readdir(dp)) != NULL)
-#else
-#define FOREACH_DIRENT(dp, dent) \
- struct { \
- struct dirent d; \
- char s[NAME_MAX + 1]; \
- } dent_; \
- struct dirent *dentp, *dent = &dent_.d; \
- int ret; \
- while ((ret = readdir_r(dp, dent, &dentp)) == 0 && dentp != NULL)
-#endif /* FOREACH_DIRENT */
-
-static h2o_buffer_t *build_dir_listing_html(h2o_mem_pool_t *pool, h2o_iovec_t path_normalized, DIR *dp)
-{
- H2O_VECTOR(char *) files = {NULL};
-
- { /* build list of files */
- FOREACH_DIRENT(dp, dent)
- {
- if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
- continue;
- h2o_vector_reserve(pool, &files, files.size + 1);
- files.entries[files.size++] = h2o_strdup(pool, dent->d_name, SIZE_MAX).base;
- }
- if (files.size > 1)
- qsort(files.entries, files.size, sizeof(files.entries[0]), cmpstrptr);
- }
-
- h2o_buffer_t *_;
- h2o_iovec_t path_normalized_escaped = h2o_htmlescape(pool, path_normalized.base, path_normalized.len);
-
- h2o_buffer_init(&_, &h2o_socket_buffer_prototype);
-
- {
- h2o_iovec_t _s = (h2o_iovec_init(H2O_STRLIT("<!DOCTYPE html>\n<TITLE>Index of ")));
- if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
- --_s.len;
- h2o_buffer_reserve(&_, _s.len);
- memcpy(_->bytes + _->size, _s.base, _s.len);
- _->size += _s.len;
- }
- {
- h2o_iovec_t _s = (path_normalized_escaped);
- if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
- --_s.len;
- h2o_buffer_reserve(&_, _s.len);
- memcpy(_->bytes + _->size, _s.base, _s.len);
- _->size += _s.len;
- }
- {
- h2o_iovec_t _s = (h2o_iovec_init(H2O_STRLIT("</TITLE>\n<H2>Index of ")));
- if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
- --_s.len;
- h2o_buffer_reserve(&_, _s.len);
- memcpy(_->bytes + _->size, _s.base, _s.len);
- _->size += _s.len;
- }
- {
- h2o_iovec_t _s = (path_normalized_escaped);
- if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
- --_s.len;
- h2o_buffer_reserve(&_, _s.len);
- memcpy(_->bytes + _->size, _s.base, _s.len);
- _->size += _s.len;
- }
- {
- h2o_iovec_t _s = (h2o_iovec_init(H2O_STRLIT("</H2>\n<UL>\n<LI><A HREF=\"..\">Parent Directory</A>\n")));
- if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
- --_s.len;
- h2o_buffer_reserve(&_, _s.len);
- memcpy(_->bytes + _->size, _s.base, _s.len);
- _->size += _s.len;
- }
-
- size_t i;
- for (i = 0; i != files.size; ++i) {
- h2o_iovec_t link_escaped = h2o_uri_escape(pool, files.entries[i], strlen(files.entries[i]), NULL);
- link_escaped = h2o_htmlescape(pool, link_escaped.base, link_escaped.len);
- h2o_iovec_t label_escaped = h2o_htmlescape(pool, files.entries[i], strlen(files.entries[i]));
- {
- h2o_iovec_t _s = (h2o_iovec_init(H2O_STRLIT("<LI><A HREF=\"")));
- if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
- --_s.len;
- h2o_buffer_reserve(&_, _s.len);
- memcpy(_->bytes + _->size, _s.base, _s.len);
- _->size += _s.len;
- }
- {
- h2o_iovec_t _s = (link_escaped);
- if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
- --_s.len;
- h2o_buffer_reserve(&_, _s.len);
- memcpy(_->bytes + _->size, _s.base, _s.len);
- _->size += _s.len;
- }
- {
- h2o_iovec_t _s = (h2o_iovec_init(H2O_STRLIT("\">")));
- if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
- --_s.len;
- h2o_buffer_reserve(&_, _s.len);
- memcpy(_->bytes + _->size, _s.base, _s.len);
- _->size += _s.len;
- }
- {
- h2o_iovec_t _s = (label_escaped);
- if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
- --_s.len;
- h2o_buffer_reserve(&_, _s.len);
- memcpy(_->bytes + _->size, _s.base, _s.len);
- _->size += _s.len;
- }
- {
- h2o_iovec_t _s = (h2o_iovec_init(H2O_STRLIT("</A>\n")));
- if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
- --_s.len;
- h2o_buffer_reserve(&_, _s.len);
- memcpy(_->bytes + _->size, _s.base, _s.len);
- _->size += _s.len;
- }
- }
- {
- h2o_iovec_t _s = (h2o_iovec_init(H2O_STRLIT("</UL>\n")));
- if (_s.len != 0 && _s.base[_s.len - 1] == '\n')
- --_s.len;
- h2o_buffer_reserve(&_, _s.len);
- memcpy(_->bytes + _->size, _s.base, _s.len);
- _->size += _s.len;
- }
-
- return _;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/headers.c b/web/server/h2o/libh2o/lib/handler/headers.c
deleted file mode 100644
index 973976b35..000000000
--- a/web/server/h2o/libh2o/lib/handler/headers.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 "h2o.h"
-
-struct st_headers_filter_t {
- h2o_filter_t super;
- h2o_headers_command_t *cmds;
-};
-
-static void on_setup_ostream(h2o_filter_t *_self, h2o_req_t *req, h2o_ostream_t **slot)
-{
- struct st_headers_filter_t *self = (void *)_self;
- h2o_headers_command_t *cmd;
-
- for (cmd = self->cmds; cmd->cmd != H2O_HEADERS_CMD_NULL; ++cmd)
- h2o_rewrite_headers(&req->pool, &req->res.headers, cmd);
-
- h2o_setup_next_ostream(req, slot);
-}
-
-void h2o_headers_register(h2o_pathconf_t *pathconf, h2o_headers_command_t *cmds)
-{
- struct st_headers_filter_t *self = (void *)h2o_create_filter(pathconf, sizeof(*self));
-
- self->super.on_setup_ostream = on_setup_ostream;
- self->cmds = cmds;
-}
-
-int h2o_headers_is_prohibited_name(const h2o_token_t *token)
-{
- /* prohibit connection-specific headers */
- if (token == H2O_TOKEN_CONNECTION || token == H2O_TOKEN_CONTENT_LENGTH || token == H2O_TOKEN_TRANSFER_ENCODING)
- return 1;
- /* prohibit headers added at protocol layer */
- if (token == H2O_TOKEN_DATE || token == H2O_TOKEN_SERVER)
- return 1;
- /* all others are permitted */
- return 0;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/headers_util.c b/web/server/h2o/libh2o/lib/handler/headers_util.c
deleted file mode 100644
index 5ecacfa54..000000000
--- a/web/server/h2o/libh2o/lib/handler/headers_util.c
+++ /dev/null
@@ -1,114 +0,0 @@
-#include "h2o.h"
-
-static h2o_header_t *find_header(h2o_headers_t *headers, h2o_headers_command_t *cmd)
-{
- size_t index;
-
- if (h2o_iovec_is_token(cmd->name)) {
- index = h2o_find_header(headers, (void *)cmd->name, SIZE_MAX);
- } else {
- index = h2o_find_header_by_str(headers, cmd->name->base, cmd->name->len, SIZE_MAX);
- }
- if (index == SIZE_MAX)
- return NULL;
- return headers->entries + index;
-}
-
-static void remove_header(h2o_headers_t *headers, h2o_headers_command_t *cmd)
-{
- size_t src, dst = 0;
-
- for (src = 0; src != headers->size; ++src) {
- if (h2o_iovec_is_token(cmd->name)) {
- if (headers->entries[src].name == cmd->name)
- continue;
- } else {
- if (h2o_memis(headers->entries[src].name->base, headers->entries[src].name->len, cmd->name->base, cmd->name->len))
- continue;
- }
- /* not matched */
- if (dst != src)
- headers->entries[dst] = headers->entries[src];
- ++dst;
- }
- headers->size = dst;
-}
-
-void h2o_headers_append_command(h2o_headers_command_t **cmds, int cmd, h2o_iovec_t *name, h2o_iovec_t value)
-{
- h2o_headers_command_t *new_cmds;
- size_t cnt;
-
- if (*cmds != NULL) {
- for (cnt = 0; (*cmds)[cnt].cmd != H2O_HEADERS_CMD_NULL; ++cnt)
- ;
- } else {
- cnt = 0;
- }
-
- new_cmds = h2o_mem_alloc_shared(NULL, (cnt + 2) * sizeof(*new_cmds), NULL);
- if (*cmds != NULL)
- memcpy(new_cmds, *cmds, cnt * sizeof(*new_cmds));
- new_cmds[cnt] = (h2o_headers_command_t){cmd, name, value};
- new_cmds[cnt + 1] = (h2o_headers_command_t){H2O_HEADERS_CMD_NULL};
-
- if (*cmds != NULL)
- h2o_mem_release_shared(*cmds);
- *cmds = new_cmds;
-}
-
-void h2o_rewrite_headers(h2o_mem_pool_t *pool, h2o_headers_t *headers, h2o_headers_command_t *cmd)
-{
- h2o_header_t *target;
-
- switch (cmd->cmd) {
- case H2O_HEADERS_CMD_ADD:
- goto AddHeader;
- case H2O_HEADERS_CMD_APPEND:
- if ((target = find_header(headers, cmd)) == NULL)
- goto AddHeader;
- goto AppendToken;
- case H2O_HEADERS_CMD_MERGE:
- if ((target = find_header(headers, cmd)) == NULL)
- goto AddHeader;
- if (h2o_contains_token(target->value.base, target->value.len, cmd->value.base, cmd->value.len, ','))
- return;
- goto AppendToken;
- case H2O_HEADERS_CMD_SET:
- remove_header(headers, cmd);
- goto AddHeader;
- case H2O_HEADERS_CMD_SETIFEMPTY:
- if (find_header(headers, cmd) != NULL)
- return;
- goto AddHeader;
- case H2O_HEADERS_CMD_UNSET:
- remove_header(headers, cmd);
- return;
- }
-
- assert(!"FIXME");
- return;
-
-AddHeader:
- if (h2o_iovec_is_token(cmd->name)) {
- h2o_add_header(pool, headers, (void *)cmd->name, NULL, cmd->value.base, cmd->value.len);
- } else {
- h2o_add_header_by_str(pool, headers, cmd->name->base, cmd->name->len, 0, NULL, cmd->value.base, cmd->value.len);
- }
- return;
-
-AppendToken:
- if (target->value.len != 0) {
- h2o_iovec_t v;
- v.len = target->value.len + 2 + cmd->value.len;
- v.base = h2o_mem_alloc_pool(pool, v.len);
- memcpy(v.base, target->value.base, target->value.len);
- v.base[target->value.len] = ',';
- v.base[target->value.len + 1] = ' ';
- memcpy(v.base + target->value.len + 2, cmd->value.base, cmd->value.len);
- target->value = v;
- } else {
- target->value = cmd->value;
- }
- return;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/http2_debug_state.c b/web/server/h2o/libh2o/lib/handler/http2_debug_state.c
deleted file mode 100644
index 0aa0bd1b1..000000000
--- a/web/server/h2o/libh2o/lib/handler/http2_debug_state.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2016 DeNA Co., Ltd., Ichito Nagata
- *
- * 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 <inttypes.h>
-#include "h2o.h"
-
-struct st_h2o_http2_debug_state_handler_t {
- h2o_handler_t super;
- int hpack_enabled;
-};
-
-static int on_req(h2o_handler_t *_self, h2o_req_t *req)
-{
- struct st_h2o_http2_debug_state_handler_t *self = (void *)_self;
-
- static h2o_generator_t generator = {NULL, NULL};
-
- if (req->conn->callbacks->get_debug_state == NULL) {
- return -1;
- }
-
- h2o_http2_debug_state_t *debug_state = req->conn->callbacks->get_debug_state(req, self->hpack_enabled);
-
- // stringify these variables to embed in Debug Header
- h2o_iovec_t conn_flow_in, conn_flow_out;
- conn_flow_in.base = h2o_mem_alloc_pool(&req->pool, sizeof(H2O_INT64_LONGEST_STR));
- conn_flow_in.len = sprintf(conn_flow_in.base, "%zd", debug_state->conn_flow_in);
- conn_flow_out.base = h2o_mem_alloc_pool(&req->pool, sizeof(H2O_INT64_LONGEST_STR));
- conn_flow_out.len = sprintf(conn_flow_out.base, "%zd", debug_state->conn_flow_out);
-
- req->res.status = 200;
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, NULL, H2O_STRLIT("application/json; charset=utf-8"));
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CACHE_CONTROL, NULL, H2O_STRLIT("no-cache, no-store"));
- h2o_add_header_by_str(&req->pool, &req->res.headers, H2O_STRLIT("conn-flow-in"), 0, NULL, conn_flow_in.base, conn_flow_in.len);
- h2o_add_header_by_str(&req->pool, &req->res.headers, H2O_STRLIT("conn-flow-out"), 0, NULL, conn_flow_out.base,
- conn_flow_out.len);
-
- h2o_start_response(req, &generator);
- h2o_send(req, debug_state->json.entries,
- h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("HEAD")) ? 0 : debug_state->json.size,
- H2O_SEND_STATE_FINAL);
- return 0;
-}
-
-void h2o_http2_debug_state_register(h2o_hostconf_t *conf, int hpack_enabled)
-{
- h2o_pathconf_t *pathconf = h2o_config_register_path(conf, "/.well-known/h2/state", 0);
- struct st_h2o_http2_debug_state_handler_t *self = (void *)h2o_create_handler(pathconf, sizeof(*self));
- self->super.on_req = on_req;
- self->hpack_enabled = hpack_enabled;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/mimemap.c b/web/server/h2o/libh2o/lib/handler/mimemap.c
deleted file mode 100644
index 764362da0..000000000
--- a/web/server/h2o/libh2o/lib/handler/mimemap.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * 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 <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "khash.h"
-#include "h2o.h"
-
-KHASH_MAP_INIT_STR(extmap, h2o_mimemap_type_t *)
-
-static inline khint_t hash_mimemap_type(h2o_mimemap_type_t *mimetype)
-{
- khint_t h = 0;
- size_t i;
- for (i = 0; i != mimetype->data.mimetype.len; ++i)
- h = (h << 5) - h + (khint_t)mimetype->data.mimetype.base[i];
- return h;
-}
-
-static inline int mimemap_type_equals(h2o_mimemap_type_t *x, h2o_mimemap_type_t *y)
-{
- return h2o_memis(x->data.mimetype.base, x->data.mimetype.len, y->data.mimetype.base, y->data.mimetype.len);
-}
-
-KHASH_INIT(typeset, h2o_mimemap_type_t *, char, 0, hash_mimemap_type, mimemap_type_equals)
-
-h2o_mime_attributes_t h2o_mime_attributes_as_is;
-
-struct st_h2o_mimemap_t {
- khash_t(extmap) * extmap;
- khash_t(typeset) * typeset; /* refs point to the entries in extmap */
- h2o_mimemap_type_t *default_type;
- size_t num_dynamic;
-};
-
-static h2o_iovec_t dupref(const char *s)
-{
- h2o_iovec_t ret;
- ret.len = strlen(s);
- ret.base = h2o_mem_alloc_shared(NULL, ret.len + 1, NULL);
- memcpy(ret.base, s, ret.len + 1);
- return ret;
-}
-
-static void on_dispose(void *_mimemap)
-{
- h2o_mimemap_t *mimemap = _mimemap;
- const char *ext;
- h2o_mimemap_type_t *type;
-
- kh_destroy(typeset, mimemap->typeset);
- kh_foreach(mimemap->extmap, ext, type, {
- h2o_mem_release_shared((char *)ext);
- h2o_mem_release_shared(type);
- });
- kh_destroy(extmap, mimemap->extmap);
- h2o_mem_release_shared(mimemap->default_type);
-}
-
-static void on_unlink(h2o_mimemap_t *mimemap, h2o_mimemap_type_t *type)
-{
- switch (type->type) {
- case H2O_MIMEMAP_TYPE_MIMETYPE:
- break;
- case H2O_MIMEMAP_TYPE_DYNAMIC:
- --mimemap->num_dynamic;
- break;
- }
-}
-
-static void on_link(h2o_mimemap_t *mimemap, h2o_mimemap_type_t *type)
-{
- switch (type->type) {
- case H2O_MIMEMAP_TYPE_MIMETYPE:
- break;
- case H2O_MIMEMAP_TYPE_DYNAMIC:
- ++mimemap->num_dynamic;
- break;
- }
-}
-
-static void rebuild_typeset(h2o_mimemap_t *mimemap)
-{
- kh_clear(typeset, mimemap->typeset);
-
- const char *ext;
- h2o_mimemap_type_t *mime;
- kh_foreach(mimemap->extmap, ext, mime, {
- if (mime->type == H2O_MIMEMAP_TYPE_MIMETYPE) {
- khiter_t iter = kh_get(typeset, mimemap->typeset, mime);
- if (iter == kh_end(mimemap->typeset)) {
- int r;
- kh_put(typeset, mimemap->typeset, mime, &r);
- }
- }
- });
-}
-
-static h2o_mimemap_type_t *create_extension_type(const char *mime, h2o_mime_attributes_t *attr)
-{
- h2o_mimemap_type_t *type = h2o_mem_alloc_shared(NULL, sizeof(*type) + strlen(mime) + 1, NULL);
- size_t i;
-
- memset(type, 0, sizeof(*type));
-
- type->type = H2O_MIMEMAP_TYPE_MIMETYPE;
-
- /* normalize-copy type->data.mimetype */
- type->data.mimetype.base = (char *)type + sizeof(*type);
- for (i = 0; mime[i] != '\0' && mime[i] != ';'; ++i)
- type->data.mimetype.base[i] = h2o_tolower(mime[i]);
- for (; mime[i] != '\0'; ++i)
- type->data.mimetype.base[i] = mime[i];
- type->data.mimetype.base[i] = '\0';
- type->data.mimetype.len = i;
-
- if (attr != NULL) {
- type->data.attr = *attr;
- } else {
- h2o_mimemap_get_default_attributes(mime, &type->data.attr);
- }
-
- return type;
-}
-
-static void dispose_dynamic_type(h2o_mimemap_type_t *type)
-{
- h2o_config_dispose_pathconf(&type->data.dynamic.pathconf);
-}
-
-static h2o_mimemap_type_t *create_dynamic_type(h2o_globalconf_t *globalconf, h2o_mimemap_t *mimemap)
-{
- h2o_mimemap_type_t *type = h2o_mem_alloc_shared(NULL, sizeof(*type), (void (*)(void *))dispose_dynamic_type);
-
- type->type = H2O_MIMEMAP_TYPE_DYNAMIC;
- memset(&type->data.dynamic, 0, sizeof(type->data.dynamic));
- h2o_config_init_pathconf(&type->data.dynamic.pathconf, globalconf, NULL, mimemap);
-
- return type;
-}
-
-h2o_mimemap_t *h2o_mimemap_create()
-{
- h2o_mimemap_t *mimemap = h2o_mem_alloc_shared(NULL, sizeof(*mimemap), on_dispose);
-
- mimemap->extmap = kh_init(extmap);
- mimemap->typeset = kh_init(typeset);
- mimemap->default_type = create_extension_type("application/octet-stream", NULL);
- mimemap->num_dynamic = 0;
- on_link(mimemap, mimemap->default_type);
-
- { /* setup the tiny default */
- static const char *default_types[] = {
-#define MIMEMAP(ext, mime) ext, mime,
-#include "mimemap/defaults.c.h"
-#undef MIMEMAP
- NULL};
- const char **p;
- for (p = default_types; *p != NULL; p += 2)
- h2o_mimemap_define_mimetype(mimemap, p[0], p[1], NULL);
- }
- rebuild_typeset(mimemap);
-
- return mimemap;
-}
-
-h2o_mimemap_t *h2o_mimemap_clone(h2o_mimemap_t *src)
-{
- h2o_mimemap_t *dst = h2o_mem_alloc_shared(NULL, sizeof(*dst), on_dispose);
- const char *ext;
- h2o_mimemap_type_t *type;
-
- dst->extmap = kh_init(extmap);
- dst->typeset = kh_init(typeset);
- kh_foreach(src->extmap, ext, type, {
- int r;
- khiter_t iter = kh_put(extmap, dst->extmap, ext, &r);
- kh_val(dst->extmap, iter) = type;
- h2o_mem_addref_shared((char *)ext);
- h2o_mem_addref_shared(type);
- on_link(dst, type);
- });
- dst->default_type = src->default_type;
- h2o_mem_addref_shared(dst->default_type);
- on_link(dst, dst->default_type);
- rebuild_typeset(dst);
-
- return dst;
-}
-
-void h2o_mimemap_on_context_init(h2o_mimemap_t *mimemap, h2o_context_t *ctx)
-{
- const char *ext;
- h2o_mimemap_type_t *type;
-
- kh_foreach(mimemap->extmap, ext, type, {
- switch (type->type) {
- case H2O_MIMEMAP_TYPE_DYNAMIC:
- h2o_context_init_pathconf_context(ctx, &type->data.dynamic.pathconf);
- break;
- case H2O_MIMEMAP_TYPE_MIMETYPE:
- break;
- }
- });
-}
-
-void h2o_mimemap_on_context_dispose(h2o_mimemap_t *mimemap, h2o_context_t *ctx)
-{
- const char *ext;
- h2o_mimemap_type_t *type;
-
- kh_foreach(mimemap->extmap, ext, type, {
- switch (type->type) {
- case H2O_MIMEMAP_TYPE_DYNAMIC:
- h2o_context_dispose_pathconf_context(ctx, &type->data.dynamic.pathconf);
- break;
- case H2O_MIMEMAP_TYPE_MIMETYPE:
- break;
- }
- });
-}
-
-int h2o_mimemap_has_dynamic_type(h2o_mimemap_t *mimemap)
-{
- return mimemap->num_dynamic != 0;
-}
-
-void h2o_mimemap_set_default_type(h2o_mimemap_t *mimemap, const char *mime, h2o_mime_attributes_t *attr)
-{
- h2o_mimemap_type_t *new_type;
-
- /* obtain or create new type */
- if ((new_type = h2o_mimemap_get_type_by_mimetype(mimemap, h2o_iovec_init(mime, strlen(mime)), 1)) != NULL &&
- (attr == NULL || memcmp(&new_type->data.attr, attr, sizeof(*attr)) == 0)) {
- h2o_mem_addref_shared(new_type);
- } else {
- new_type = create_extension_type(mime, attr);
- }
-
- /* unlink the old one */
- on_unlink(mimemap, mimemap->default_type);
- h2o_mem_release_shared(mimemap->default_type);
-
- /* update */
- mimemap->default_type = new_type;
- on_link(mimemap, new_type);
- rebuild_typeset(mimemap);
-}
-
-static void set_type(h2o_mimemap_t *mimemap, const char *ext, h2o_mimemap_type_t *type)
-{
- /* obtain key, and remove the old value */
- khiter_t iter = kh_get(extmap, mimemap->extmap, ext);
- if (iter != kh_end(mimemap->extmap)) {
- h2o_mimemap_type_t *oldtype = kh_val(mimemap->extmap, iter);
- on_unlink(mimemap, oldtype);
- h2o_mem_release_shared(oldtype);
- } else {
- int ret;
- iter = kh_put(extmap, mimemap->extmap, dupref(ext).base, &ret);
- assert(iter != kh_end(mimemap->extmap));
- }
-
- /* update */
- h2o_mem_addref_shared(type);
- kh_val(mimemap->extmap, iter) = type;
- on_link(mimemap, type);
- rebuild_typeset(mimemap);
-}
-
-void h2o_mimemap_define_mimetype(h2o_mimemap_t *mimemap, const char *ext, const char *mime, h2o_mime_attributes_t *attr)
-{
- h2o_mimemap_type_t *new_type;
-
- if ((new_type = h2o_mimemap_get_type_by_mimetype(mimemap, h2o_iovec_init(mime, strlen(mime)), 1)) != NULL &&
- (attr == NULL || memcmp(&new_type->data.attr, attr, sizeof(*attr)) == 0)) {
- h2o_mem_addref_shared(new_type);
- } else {
- new_type = create_extension_type(mime, attr);
- }
- set_type(mimemap, ext, new_type);
- h2o_mem_release_shared(new_type);
-}
-
-h2o_mimemap_type_t *h2o_mimemap_define_dynamic(h2o_mimemap_t *mimemap, const char **exts, h2o_globalconf_t *globalconf)
-{
- /* FIXME: fix memory leak introduced by this a cyclic link (mimemap -> new_type -> mimemap)
- * note also that we may want to update the reference from the dynamic type to the mimemap as we clone the mimemap,
- * but doing so naively would cause unnecessary copies of fastcgi.spawns... */
- h2o_mimemap_type_t *new_type = create_dynamic_type(globalconf, mimemap);
- size_t i;
-
- for (i = 0; exts[i] != NULL; ++i)
- set_type(mimemap, exts[i], new_type);
- h2o_mem_release_shared(new_type);
- return new_type;
-}
-
-void h2o_mimemap_remove_type(h2o_mimemap_t *mimemap, const char *ext)
-{
- khiter_t iter = kh_get(extmap, mimemap->extmap, ext);
- if (iter != kh_end(mimemap->extmap)) {
- const char *key = kh_key(mimemap->extmap, iter);
- h2o_mimemap_type_t *type = kh_val(mimemap->extmap, iter);
- on_unlink(mimemap, type);
- h2o_mem_release_shared(type);
- kh_del(extmap, mimemap->extmap, iter);
- h2o_mem_release_shared((char *)key);
- rebuild_typeset(mimemap);
- }
-}
-
-void h2o_mimemap_clear_types(h2o_mimemap_t *mimemap)
-{
- khiter_t iter;
-
- for (iter = kh_begin(mimemap->extmap); iter != kh_end(mimemap->extmap); ++iter) {
- if (!kh_exist(mimemap->extmap, iter)) continue;
- const char *key = kh_key(mimemap->extmap, iter);
- h2o_mimemap_type_t *type = kh_val(mimemap->extmap, iter);
- on_unlink(mimemap, type);
- h2o_mem_release_shared(type);
- kh_del(extmap, mimemap->extmap, iter);
- h2o_mem_release_shared((char *)key);
- }
- rebuild_typeset(mimemap);
-}
-
-h2o_mimemap_type_t *h2o_mimemap_get_default_type(h2o_mimemap_t *mimemap)
-{
- return mimemap->default_type;
-}
-
-h2o_mimemap_type_t *h2o_mimemap_get_type_by_extension(h2o_mimemap_t *mimemap, h2o_iovec_t ext)
-{
- char lcbuf[256];
-
- if (0 < ext.len && ext.len < sizeof(lcbuf)) {
- memcpy(lcbuf, ext.base, ext.len);
- h2o_strtolower(lcbuf, ext.len);
- lcbuf[ext.len] = '\0';
- khiter_t iter = kh_get(extmap, mimemap->extmap, lcbuf);
- if (iter != kh_end(mimemap->extmap))
- return kh_val(mimemap->extmap, iter);
- }
- return mimemap->default_type;
-}
-
-h2o_mimemap_type_t *h2o_mimemap_get_type_by_mimetype(h2o_mimemap_t *mimemap, h2o_iovec_t mime, int exact_match_only)
-{
- h2o_mimemap_type_t key = {H2O_MIMEMAP_TYPE_MIMETYPE};
- khiter_t iter;
- size_t type_end_at;
-
- /* exact match */
- key.data.mimetype = mime;
- if ((iter = kh_get(typeset, mimemap->typeset, &key)) != kh_end(mimemap->typeset))
- return kh_key(mimemap->typeset, iter);
-
- if (!exact_match_only) {
- /* determine the end of the type */
- for (type_end_at = 0; type_end_at != mime.len; ++type_end_at)
- if (mime.base[type_end_at] == ';' || mime.base[type_end_at] == ' ')
- goto HasAttributes;
- }
- return NULL;
-
-HasAttributes:
- /* perform search without attributes */
- key.data.mimetype.len = type_end_at;
- if ((iter = kh_get(typeset, mimemap->typeset, &key)) != kh_end(mimemap->typeset))
- return kh_key(mimemap->typeset, iter);
-
- return NULL;
-}
-
-void h2o_mimemap_get_default_attributes(const char *_mime, h2o_mime_attributes_t *attr)
-{
- char *mime = alloca(strlen(_mime) + 1);
- strcpy(mime, _mime);
-
- const char *type_end_at;
-
- if ((type_end_at = strchr(mime, ';')) == NULL)
- type_end_at = mime + strlen(mime);
-
- *attr = (h2o_mime_attributes_t){0};
-
- if (h2o_memis(mime, type_end_at - mime, H2O_STRLIT("text/css")) ||
- h2o_memis(mime, type_end_at - mime, H2O_STRLIT("application/ecmascript")) ||
- h2o_memis(mime, type_end_at - mime, H2O_STRLIT("application/javascript")) ||
- h2o_memis(mime, type_end_at - mime, H2O_STRLIT("text/ecmascript")) ||
- h2o_memis(mime, type_end_at - mime, H2O_STRLIT("text/javascript"))) {
- attr->is_compressible = 1;
- attr->priority = H2O_MIME_ATTRIBUTE_PRIORITY_HIGHEST;
- } else if (h2o_memis(mime, type_end_at - mime, H2O_STRLIT("application/json")) || strncmp(mime, "text/", 5) == 0 ||
- h2o_strstr(mime, type_end_at - mime, H2O_STRLIT("+xml")) != SIZE_MAX) {
- attr->is_compressible = 1;
- }
-}
diff --git a/web/server/h2o/libh2o/lib/handler/mimemap/defaults.c.h b/web/server/h2o/libh2o/lib/handler/mimemap/defaults.c.h
deleted file mode 100644
index a395e0ccb..000000000
--- a/web/server/h2o/libh2o/lib/handler/mimemap/defaults.c.h
+++ /dev/null
@@ -1,109 +0,0 @@
-MIMEMAP("3gp", "video/3gpp")
-MIMEMAP("3gpp", "video/3gpp")
-MIMEMAP("7z", "application/x-7z-compressed")
-MIMEMAP("ai", "application/postscript")
-MIMEMAP("apng", "image/apng")
-MIMEMAP("asf", "video/x-ms-asf")
-MIMEMAP("asx", "video/x-ms-asf")
-MIMEMAP("atom", "application/atom+xml")
-MIMEMAP("avi", "video/x-msvideo")
-MIMEMAP("bin", "application/octet-stream")
-MIMEMAP("bmp", "image/x-ms-bmp")
-MIMEMAP("cco", "application/x-cocoa")
-MIMEMAP("crt", "application/x-x509-ca-cert")
-MIMEMAP("css", "text/css")
-MIMEMAP("csv", "text/csv")
-MIMEMAP("deb", "application/octet-stream")
-MIMEMAP("der", "application/x-x509-ca-cert")
-MIMEMAP("dll", "application/octet-stream")
-MIMEMAP("dmg", "application/octet-stream")
-MIMEMAP("doc", "application/msword")
-MIMEMAP("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
-MIMEMAP("ear", "application/java-archive")
-MIMEMAP("eot", "application/vnd.ms-fontobject")
-MIMEMAP("eps", "application/postscript")
-MIMEMAP("exe", "application/octet-stream")
-MIMEMAP("flv", "video/x-flv")
-MIMEMAP("gif", "image/gif")
-MIMEMAP("hqx", "application/mac-binhex40")
-MIMEMAP("htc", "text/x-component")
-MIMEMAP("htm", "text/html")
-MIMEMAP("html", "text/html")
-MIMEMAP("ico", "image/x-icon")
-MIMEMAP("img", "application/octet-stream")
-MIMEMAP("iso", "application/octet-stream")
-MIMEMAP("jad", "text/vnd.sun.j2me.app-descriptor")
-MIMEMAP("jar", "application/java-archive")
-MIMEMAP("jardiff", "application/x-java-archive-diff")
-MIMEMAP("jng", "image/x-jng")
-MIMEMAP("jnlp", "application/x-java-jnlp-file")
-MIMEMAP("jpeg", "image/jpeg")
-MIMEMAP("jpg", "image/jpeg")
-MIMEMAP("jxr", "image/jxr")
-MIMEMAP("js", "application/javascript")
-MIMEMAP("json", "application/json")
-MIMEMAP("kar", "audio/midi")
-MIMEMAP("kml", "application/vnd.google-earth.kml+xml")
-MIMEMAP("kmz", "application/vnd.google-earth.kmz")
-MIMEMAP("m3u8", "application/vnd.apple.mpegurl")
-MIMEMAP("m4a", "audio/x-m4a")
-MIMEMAP("m4v", "video/x-m4v")
-MIMEMAP("md", "text/markdown")
-MIMEMAP("mid", "audio/midi")
-MIMEMAP("midi", "audio/midi")
-MIMEMAP("mml", "text/mathml")
-MIMEMAP("mng", "video/x-mng")
-MIMEMAP("mov", "video/quicktime")
-MIMEMAP("mp3", "audio/mpeg")
-MIMEMAP("mp4", "video/mp4")
-MIMEMAP("mpeg", "video/mpeg")
-MIMEMAP("mpg", "video/mpeg")
-MIMEMAP("msi", "application/octet-stream")
-MIMEMAP("msm", "application/octet-stream")
-MIMEMAP("msp", "application/octet-stream")
-MIMEMAP("ogg", "audio/ogg")
-MIMEMAP("opus", "audio/ogg")
-MIMEMAP("pdb", "application/x-pilot")
-MIMEMAP("pdf", "application/pdf")
-MIMEMAP("pem", "application/x-x509-ca-cert")
-MIMEMAP("pl", "application/x-perl")
-MIMEMAP("pm", "application/x-perl")
-MIMEMAP("png", "image/png")
-MIMEMAP("ppt", "application/vnd.ms-powerpoint")
-MIMEMAP("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation")
-MIMEMAP("prc", "application/x-pilot")
-MIMEMAP("ps", "application/postscript")
-MIMEMAP("ra", "audio/x-realaudio")
-MIMEMAP("rar", "application/x-rar-compressed")
-MIMEMAP("rpm", "application/x-redhat-package-manager")
-MIMEMAP("rss", "application/rss+xml")
-MIMEMAP("rtf", "application/rtf")
-MIMEMAP("run", "application/x-makeself")
-MIMEMAP("sea", "application/x-sea")
-MIMEMAP("shtml", "text/html")
-MIMEMAP("sit", "application/x-stuffit")
-MIMEMAP("svg", "image/svg+xml")
-MIMEMAP("svgz", "image/svg+xml")
-MIMEMAP("swf", "application/x-shockwave-flash")
-MIMEMAP("tcl", "application/x-tcl")
-MIMEMAP("tif", "image/tiff")
-MIMEMAP("tiff", "image/tiff")
-MIMEMAP("tk", "application/x-tcl")
-MIMEMAP("ts", "video/mp2t")
-MIMEMAP("txt", "text/plain")
-MIMEMAP("war", "application/java-archive")
-MIMEMAP("wbmp", "image/vnd.wap.wbmp")
-MIMEMAP("webm", "video/webm")
-MIMEMAP("webp", "image/webp")
-MIMEMAP("wml", "text/vnd.wap.wml")
-MIMEMAP("wmlc", "application/vnd.wap.wmlc")
-MIMEMAP("wmv", "video/x-ms-wmv")
-MIMEMAP("woff", "application/font-woff")
-MIMEMAP("woff2", "font/woff2")
-MIMEMAP("xhtml", "application/xhtml+xml")
-MIMEMAP("xls", "application/vnd.ms-excel")
-MIMEMAP("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
-MIMEMAP("xml", "text/xml")
-MIMEMAP("xpi", "application/x-xpinstall")
-MIMEMAP("xspf", "application/xspf+xml")
-MIMEMAP("zip", "application/zip")
diff --git a/web/server/h2o/libh2o/lib/handler/mruby.c b/web/server/h2o/libh2o/lib/handler/mruby.c
deleted file mode 100644
index af2af53fd..000000000
--- a/web/server/h2o/libh2o/lib/handler/mruby.c
+++ /dev/null
@@ -1,938 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Ryosuke Matsumoto,
- * Masayoshi Takahashi
- *
- * 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 <errno.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <mruby.h>
-#include <mruby/proc.h>
-#include <mruby/array.h>
-#include <mruby/class.h>
-#include <mruby/compile.h>
-#include <mruby/error.h>
-#include <mruby/hash.h>
-#include <mruby/string.h>
-#include <mruby/throw.h>
-#include <mruby/variable.h>
-#include <mruby_input_stream.h>
-#include "h2o.h"
-#include "h2o/mruby_.h"
-#include "mruby/embedded.c.h"
-
-#define STATUS_FALLTHRU 399
-#define FALLTHRU_SET_PREFIX "x-fallthru-set-"
-
-#define FREEZE_STRING(v) MRB_SET_FROZEN_FLAG(mrb_obj_ptr(v))
-
-__thread h2o_mruby_generator_t *h2o_mruby_current_generator = NULL;
-
-void h2o_mruby__assert_failed(mrb_state *mrb, const char *file, int line)
-{
- mrb_value obj = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0);
- struct RString *error = mrb_str_ptr(obj);
- fprintf(stderr, "unexpected ruby error at file: \"%s\", line %d: %s", file, line, error->as.heap.ptr);
- abort();
-}
-
-void h2o_mruby_setup_globals(mrb_state *mrb)
-{
- const char *root = getenv("H2O_ROOT");
- if (root == NULL)
- root = H2O_TO_STR(H2O_ROOT);
- mrb_gv_set(mrb, mrb_intern_lit(mrb, "$H2O_ROOT"), mrb_str_new(mrb, root, strlen(root)));
-
- h2o_mruby_eval_expr(mrb, "$LOAD_PATH << \"#{$H2O_ROOT}/share/h2o/mruby\"");
- h2o_mruby_assert(mrb);
-
- /* require core modules and include built-in libraries */
- h2o_mruby_eval_expr(mrb, "require \"#{$H2O_ROOT}/share/h2o/mruby/preloads.rb\"");
- if (mrb->exc != NULL) {
- if (mrb_obj_is_instance_of(mrb, mrb_obj_value(mrb->exc), mrb_class_get(mrb, "LoadError"))) {
- fprintf(stderr, "file \"%s/%s\" not found. Did you forget to run `make install` ?", root,
- "share/h2o/mruby/preloads.rb");
- } else {
- mrb_value obj = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0);
- struct RString *error = mrb_str_ptr(obj);
- fprintf(stderr, "an error occurred while loading %s/%s: %s", root, "share/h2o/mruby/preloads.rb", error->as.heap.ptr);
- }
- abort();
- }
-}
-
-mrb_value h2o_mruby_to_str(mrb_state *mrb, mrb_value v)
-{
- if (!mrb_string_p(v))
- H2O_MRUBY_EXEC_GUARD({ v = mrb_str_to_str(mrb, v); });
- return v;
-}
-
-mrb_value h2o_mruby_eval_expr(mrb_state *mrb, const char *expr)
-{
- return mrb_funcall(mrb, mrb_top_self(mrb), "eval", 1, mrb_str_new_cstr(mrb, expr));
-}
-
-void h2o_mruby_define_callback(mrb_state *mrb, const char *name, int id)
-{
- mrb_value args[2];
- args[0] = mrb_str_new_cstr(mrb, name);
- args[1] = mrb_fixnum_value(id);
- mrb_funcall_argv(mrb, mrb_top_self(mrb), mrb_intern_lit(mrb, "_h2o_define_callback"), 2, args);
-
- if (mrb->exc != NULL) {
- fprintf(stderr, "failed to define mruby function: %s\n", name);
- h2o_mruby_assert(mrb);
- }
-}
-
-mrb_value h2o_mruby_create_data_instance(mrb_state *mrb, mrb_value class_obj, void *ptr, const mrb_data_type *type)
-{
- struct RClass *klass = mrb_class_ptr(class_obj);
- struct RData *data = mrb_data_object_alloc(mrb, klass, ptr, type);
- return mrb_obj_value(data);
-}
-
-mrb_value h2o_mruby_compile_code(mrb_state *mrb, h2o_mruby_config_vars_t *config, char *errbuf)
-{
- mrbc_context *cxt;
- struct mrb_parser_state *parser;
- struct RProc *proc = NULL;
- mrb_value result = mrb_nil_value();
-
- /* parse */
- if ((cxt = mrbc_context_new(mrb)) == NULL) {
- fprintf(stderr, "%s: no memory\n", H2O_MRUBY_MODULE_NAME);
- abort();
- }
- if (config->path != NULL)
- mrbc_filename(mrb, cxt, config->path);
- cxt->capture_errors = 1;
- cxt->lineno = config->lineno;
- if ((parser = mrb_parse_nstring(mrb, config->source.base, (int)config->source.len, cxt)) == NULL) {
- fprintf(stderr, "%s: no memory\n", H2O_MRUBY_MODULE_NAME);
- abort();
- }
- /* return erro if errbuf is supplied, or abort */
- if (parser->nerr != 0) {
- if (errbuf == NULL) {
- fprintf(stderr, "%s: internal error (unexpected state)\n", H2O_MRUBY_MODULE_NAME);
- abort();
- }
- snprintf(errbuf, 256, "line %d:%s", parser->error_buffer[0].lineno, parser->error_buffer[0].message);
- strcat(errbuf, "\n\n");
- if (h2o_str_at_position(errbuf + strlen(errbuf), config->source.base, config->source.len,
- parser->error_buffer[0].lineno - config->lineno + 1, parser->error_buffer[0].column) != 0) {
- /* remove trailing "\n\n" in case we failed to append the source code at the error location */
- errbuf[strlen(errbuf) - 2] = '\0';
- }
- goto Exit;
- }
- /* generate code */
- if ((proc = mrb_generate_code(mrb, parser)) == NULL) {
- fprintf(stderr, "%s: internal error (mrb_generate_code failed)\n", H2O_MRUBY_MODULE_NAME);
- abort();
- }
-
- /* adjust stack length of toplevel environment (see https://github.com/h2o/h2o/issues/1464#issuecomment-337880408) */
- if (mrb->c->cibase->env) {
- struct REnv *e = mrb->c->cibase->env;
- if (MRB_ENV_STACK_LEN(e) < proc->body.irep->nlocals)
- MRB_SET_ENV_STACK_LEN(e, proc->body.irep->nlocals);
- }
-
- /* reset configuration context */
- h2o_mruby_eval_expr(mrb, "H2O::ConfigurationContext.reset");
- h2o_mruby_assert(mrb);
-
- /* run code and generate handler */
- result = mrb_run(mrb, proc, mrb_top_self(mrb));
- if (mrb->exc != NULL) {
- mrb_value obj = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0);
- struct RString *error = mrb_str_ptr(obj);
- snprintf(errbuf, 256, "%s", error->as.heap.ptr);
- mrb->exc = 0;
- result = mrb_nil_value();
- goto Exit;
- } else if (mrb_nil_p(result)) {
- snprintf(errbuf, 256, "returned value is not callable");
- goto Exit;
- }
-
- /* call post_handler_generation hooks */
- mrb_funcall_argv(mrb, h2o_mruby_eval_expr(mrb, "H2O::ConfigurationContext.instance"),
- mrb_intern_lit(mrb, "call_post_handler_generation_hooks"), 1, &result);
- if (mrb->exc != NULL) {
- mrb_value obj = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0);
- struct RString *error = mrb_str_ptr(obj);
- snprintf(errbuf, 256, "%s", error->as.heap.ptr);
- mrb->exc = 0;
- result = mrb_nil_value();
- goto Exit;
- }
-
-Exit:
- mrb_parser_free(parser);
- mrbc_context_free(mrb, cxt);
- return result;
-}
-
-static h2o_iovec_t convert_header_name_to_env(h2o_mem_pool_t *pool, const char *name, size_t len)
-{
-#define KEY_PREFIX "HTTP_"
-#define KEY_PREFIX_LEN (sizeof(KEY_PREFIX) - 1)
-
- h2o_iovec_t ret;
-
- ret.len = len + KEY_PREFIX_LEN;
- ret.base = h2o_mem_alloc_pool(pool, ret.len);
-
- memcpy(ret.base, KEY_PREFIX, KEY_PREFIX_LEN);
-
- char *d = ret.base + KEY_PREFIX_LEN;
- for (; len != 0; ++name, --len)
- *d++ = *name == '-' ? '_' : h2o_toupper(*name);
-
- return ret;
-
-#undef KEY_PREFIX
-#undef KEY_PREFIX_LEN
-}
-
-static mrb_value build_constants(mrb_state *mrb, const char *server_name, size_t server_name_len)
-{
- mrb_value ary = mrb_ary_new_capa(mrb, H2O_MRUBY_NUM_CONSTANTS);
- mrb_int i;
-
- int gc_arena = mrb_gc_arena_save(mrb);
-
- {
- h2o_mem_pool_t pool;
- h2o_mem_init_pool(&pool);
- for (i = 0; i != H2O_MAX_TOKENS; ++i) {
- const h2o_token_t *token = h2o__tokens + i;
- mrb_value lit = mrb_nil_value();
- if (token == H2O_TOKEN_CONTENT_TYPE) {
- lit = mrb_str_new_lit(mrb, "CONTENT_TYPE");
- } else if (token->buf.len != 0) {
- h2o_iovec_t n = convert_header_name_to_env(&pool, token->buf.base, token->buf.len);
- lit = mrb_str_new(mrb, n.base, n.len);
- }
- if (mrb_string_p(lit)) {
- FREEZE_STRING(lit);
- mrb_ary_set(mrb, ary, i, lit);
- }
- }
- h2o_mem_clear_pool(&pool);
- }
-
-#define SET_STRING(idx, value) \
- do { \
- mrb_value lit = (value); \
- FREEZE_STRING(lit); \
- mrb_ary_set(mrb, ary, idx, lit); \
- } while (0)
-#define SET_LITERAL(idx, str) SET_STRING(idx, mrb_str_new_lit(mrb, str))
-
- SET_LITERAL(H2O_MRUBY_LIT_REQUEST_METHOD, "REQUEST_METHOD");
- SET_LITERAL(H2O_MRUBY_LIT_SCRIPT_NAME, "SCRIPT_NAME");
- SET_LITERAL(H2O_MRUBY_LIT_PATH_INFO, "PATH_INFO");
- SET_LITERAL(H2O_MRUBY_LIT_QUERY_STRING, "QUERY_STRING");
- SET_LITERAL(H2O_MRUBY_LIT_SERVER_NAME, "SERVER_NAME");
- SET_LITERAL(H2O_MRUBY_LIT_SERVER_ADDR, "SERVER_ADDR");
- SET_LITERAL(H2O_MRUBY_LIT_SERVER_PORT, "SERVER_PORT");
- SET_LITERAL(H2O_MRUBY_LIT_SERVER_PROTOCOL, "SERVER_PROTOCOL");
- SET_LITERAL(H2O_MRUBY_LIT_CONTENT_LENGTH, "CONTENT_LENGTH");
- SET_LITERAL(H2O_MRUBY_LIT_REMOTE_ADDR, "REMOTE_ADDR");
- SET_LITERAL(H2O_MRUBY_LIT_REMOTE_PORT, "REMOTE_PORT");
- SET_LITERAL(H2O_MRUBY_LIT_REMOTE_USER, "REMOTE_USER");
- SET_LITERAL(H2O_MRUBY_LIT_RACK_URL_SCHEME, "rack.url_scheme");
- SET_LITERAL(H2O_MRUBY_LIT_RACK_MULTITHREAD, "rack.multithread");
- SET_LITERAL(H2O_MRUBY_LIT_RACK_MULTIPROCESS, "rack.multiprocess");
- SET_LITERAL(H2O_MRUBY_LIT_RACK_RUN_ONCE, "rack.run_once");
- SET_LITERAL(H2O_MRUBY_LIT_RACK_HIJACK_, "rack.hijack?");
- SET_LITERAL(H2O_MRUBY_LIT_RACK_INPUT, "rack.input");
- SET_LITERAL(H2O_MRUBY_LIT_RACK_ERRORS, "rack.errors");
- SET_LITERAL(H2O_MRUBY_LIT_SERVER_SOFTWARE, "SERVER_SOFTWARE");
- SET_STRING(H2O_MRUBY_LIT_SERVER_SOFTWARE_VALUE, mrb_str_new(mrb, server_name, server_name_len));
- SET_LITERAL(H2O_MRUBY_LIT_SEPARATOR_COMMA, ", ");
- SET_LITERAL(H2O_MRUBY_LIT_SEPARATOR_SEMICOLON, "; ");
-
-#undef SET_LITERAL
-#undef SET_STRING
-
- h2o_mruby_eval_expr(mrb, H2O_MRUBY_CODE_CORE);
- h2o_mruby_assert(mrb);
-
- mrb_ary_set(mrb, ary, H2O_MRUBY_PROC_EACH_TO_ARRAY,
- mrb_funcall(mrb, mrb_obj_value(mrb->kernel_module), "_h2o_proc_each_to_array", 0));
- h2o_mruby_assert(mrb);
-
- /* sends exception using H2O_MRUBY_CALLBACK_ID_EXCEPTION_RAISED */
- mrb_ary_set(mrb, ary, H2O_MRUBY_PROC_APP_TO_FIBER,
- mrb_funcall(mrb, mrb_obj_value(mrb->kernel_module), "_h2o_proc_app_to_fiber", 0));
- h2o_mruby_assert(mrb);
-
- mrb_gc_arena_restore(mrb, gc_arena);
- return ary;
-}
-
-static h2o_mruby_shared_context_t *create_shared_context(h2o_context_t *ctx)
-{
- /* init mruby in every thread */
- h2o_mruby_shared_context_t *shared_ctx = h2o_mem_alloc(sizeof(*shared_ctx));
- if ((shared_ctx->mrb = mrb_open()) == NULL) {
- fprintf(stderr, "%s: no memory\n", H2O_MRUBY_MODULE_NAME);
- abort();
- }
- h2o_mruby_setup_globals(shared_ctx->mrb);
- shared_ctx->constants = build_constants(shared_ctx->mrb, ctx->globalconf->server_name.base, ctx->globalconf->server_name.len);
- shared_ctx->symbols.sym_call = mrb_intern_lit(shared_ctx->mrb, "call");
- shared_ctx->symbols.sym_close = mrb_intern_lit(shared_ctx->mrb, "close");
- shared_ctx->symbols.sym_method = mrb_intern_lit(shared_ctx->mrb, "method");
- shared_ctx->symbols.sym_headers = mrb_intern_lit(shared_ctx->mrb, "headers");
- shared_ctx->symbols.sym_body = mrb_intern_lit(shared_ctx->mrb, "body");
- shared_ctx->symbols.sym_async = mrb_intern_lit(shared_ctx->mrb, "async");
-
- h2o_mruby_send_chunked_init_context(shared_ctx);
- h2o_mruby_http_request_init_context(shared_ctx);
-
- return shared_ctx;
-}
-
-static void dispose_shared_context(void *data)
-{
- if (data == NULL)
- return;
- h2o_mruby_shared_context_t *shared_ctx = (h2o_mruby_shared_context_t *)data;
- mrb_close(shared_ctx->mrb);
- free(shared_ctx);
-}
-
-static h2o_mruby_shared_context_t *get_shared_context(h2o_context_t *ctx)
-{
- static size_t key = SIZE_MAX;
- void **data = h2o_context_get_storage(ctx, &key, dispose_shared_context);
- if (*data == NULL) {
- *data = create_shared_context(ctx);
- }
- return *data;
-}
-
-static void on_context_init(h2o_handler_t *_handler, h2o_context_t *ctx)
-{
- h2o_mruby_handler_t *handler = (void *)_handler;
- h2o_mruby_context_t *handler_ctx = h2o_mem_alloc(sizeof(*handler_ctx));
-
- handler_ctx->handler = handler;
- handler_ctx->shared = get_shared_context(ctx);
-
- /* compile code (must be done for each thread) */
- int arena = mrb_gc_arena_save(handler_ctx->shared->mrb);
- mrb_value proc = h2o_mruby_compile_code(handler_ctx->shared->mrb, &handler->config, NULL);
-
- handler_ctx->proc =
- mrb_funcall_argv(handler_ctx->shared->mrb, mrb_ary_entry(handler_ctx->shared->constants, H2O_MRUBY_PROC_APP_TO_FIBER),
- handler_ctx->shared->symbols.sym_call, 1, &proc);
- h2o_mruby_assert(handler_ctx->shared->mrb);
- mrb_gc_arena_restore(handler_ctx->shared->mrb, arena);
- mrb_gc_protect(handler_ctx->shared->mrb, handler_ctx->proc);
-
- h2o_context_set_handler_context(ctx, &handler->super, handler_ctx);
-}
-
-static void on_context_dispose(h2o_handler_t *_handler, h2o_context_t *ctx)
-{
- h2o_mruby_handler_t *handler = (void *)_handler;
- h2o_mruby_context_t *handler_ctx = h2o_context_get_handler_context(ctx, &handler->super);
-
- if (handler_ctx == NULL)
- return;
-
- free(handler_ctx);
-}
-
-static void on_handler_dispose(h2o_handler_t *_handler)
-{
- h2o_mruby_handler_t *handler = (void *)_handler;
-
- free(handler->config.source.base);
- free(handler->config.path);
- free(handler);
-}
-
-static void report_exception(h2o_req_t *req, mrb_state *mrb)
-{
- mrb_value obj = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0);
- struct RString *error = mrb_str_ptr(obj);
- h2o_req_log_error(req, H2O_MRUBY_MODULE_NAME, "mruby raised: %s\n", error->as.heap.ptr);
- mrb->exc = NULL;
-}
-
-static void stringify_address(h2o_conn_t *conn, socklen_t (*cb)(h2o_conn_t *conn, struct sockaddr *), mrb_state *mrb,
- mrb_value *host, mrb_value *port)
-{
- struct sockaddr_storage ss;
- socklen_t sslen;
- char buf[NI_MAXHOST];
-
- *host = mrb_nil_value();
- *port = mrb_nil_value();
-
- if ((sslen = cb(conn, (void *)&ss)) == 0)
- return;
- size_t l = h2o_socket_getnumerichost((void *)&ss, sslen, buf);
- if (l != SIZE_MAX)
- *host = mrb_str_new(mrb, buf, l);
- int32_t p = h2o_socket_getport((void *)&ss);
- if (p != -1) {
- l = (int)sprintf(buf, "%" PRIu16, (uint16_t)p);
- *port = mrb_str_new(mrb, buf, l);
- }
-}
-
-static void on_rack_input_free(mrb_state *mrb, const char *base, mrb_int len, void *_input_stream)
-{
- /* reset ref to input_stream */
- mrb_value *input_stream = _input_stream;
- *input_stream = mrb_nil_value();
-}
-
-static int build_env_sort_header_cb(const void *_x, const void *_y)
-{
- const h2o_header_t *x = *(const h2o_header_t **)_x, *y = *(const h2o_header_t **)_y;
- if (x->name->len < y->name->len)
- return -1;
- if (x->name->len > y->name->len)
- return 1;
- if (x->name->base != y->name->base) {
- int r = memcmp(x->name->base, y->name->base, x->name->len);
- if (r != 0)
- return r;
- }
- assert(x != y);
- /* the order of the headers having the same name needs to be retained */
- return x < y ? -1 : 1;
-}
-
-static mrb_value build_path_info(mrb_state *mrb, h2o_req_t *req, size_t confpath_len_wo_slash)
-{
- if (req->path_normalized.len == confpath_len_wo_slash)
- return mrb_str_new_lit(mrb, "");
-
- assert(req->path_normalized.len > confpath_len_wo_slash);
-
- size_t path_info_start, path_info_end = req->query_at != SIZE_MAX ? req->query_at : req->path.len;
-
- if (req->norm_indexes == NULL) {
- path_info_start = confpath_len_wo_slash;
- } else if (req->norm_indexes[0] == 0 && confpath_len_wo_slash == 0) {
- /* path without leading slash */
- path_info_start = 0;
- } else {
- path_info_start = req->norm_indexes[confpath_len_wo_slash] - 1;
- }
-
- return mrb_str_new(mrb, req->path.base + path_info_start, path_info_end - path_info_start);
-}
-
-static mrb_value build_env(h2o_mruby_generator_t *generator)
-{
- h2o_mruby_shared_context_t *shared = generator->ctx->shared;
- mrb_state *mrb = shared->mrb;
- mrb_value env = mrb_hash_new_capa(mrb, 16);
- char http_version[sizeof("HTTP/1.0")];
- size_t http_version_sz;
-
- /* environment */
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_REQUEST_METHOD),
- mrb_str_new(mrb, generator->req->method.base, generator->req->method.len));
-
- size_t confpath_len_wo_slash = generator->req->pathconf->path.len;
- if (generator->req->pathconf->path.base[generator->req->pathconf->path.len - 1] == '/')
- --confpath_len_wo_slash;
- assert(confpath_len_wo_slash <= generator->req->path_normalized.len);
-
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_SCRIPT_NAME),
- mrb_str_new(mrb, generator->req->pathconf->path.base, confpath_len_wo_slash));
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_PATH_INFO), build_path_info(mrb, generator->req, confpath_len_wo_slash));
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_QUERY_STRING),
- generator->req->query_at != SIZE_MAX ? mrb_str_new(mrb, generator->req->path.base + generator->req->query_at + 1,
- generator->req->path.len - (generator->req->query_at + 1))
- : mrb_str_new_lit(mrb, ""));
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_SERVER_NAME),
- mrb_str_new(mrb, generator->req->hostconf->authority.host.base, generator->req->hostconf->authority.host.len));
- http_version_sz = h2o_stringify_protocol_version(http_version, generator->req->version);
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_SERVER_PROTOCOL),
- mrb_str_new(mrb, http_version, http_version_sz));
- {
- mrb_value h, p;
- stringify_address(generator->req->conn, generator->req->conn->callbacks->get_sockname, mrb, &h, &p);
- if (!mrb_nil_p(h))
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_SERVER_ADDR), h);
- if (!mrb_nil_p(p))
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_SERVER_PORT), p);
- }
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_TOKEN_HOST - h2o__tokens),
- mrb_str_new(mrb, generator->req->authority.base, generator->req->authority.len));
- if (generator->req->entity.base != NULL) {
- char buf[32];
- int l = sprintf(buf, "%zu", generator->req->entity.len);
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_CONTENT_LENGTH), mrb_str_new(mrb, buf, l));
- generator->rack_input = mrb_input_stream_value(mrb, NULL, 0);
- mrb_input_stream_set_data(mrb, generator->rack_input, generator->req->entity.base, (mrb_int)generator->req->entity.len, 0,
- on_rack_input_free, &generator->rack_input);
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_RACK_INPUT), generator->rack_input);
- }
- {
- mrb_value h, p;
- stringify_address(generator->req->conn, generator->req->conn->callbacks->get_peername, mrb, &h, &p);
- if (!mrb_nil_p(h))
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_REMOTE_ADDR), h);
- if (!mrb_nil_p(p))
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_REMOTE_PORT), p);
- }
- {
- size_t i;
- for (i = 0; i != generator->req->env.size; i += 2) {
- h2o_iovec_t *name = generator->req->env.entries + i, *value = name + 1;
- mrb_hash_set(mrb, env, mrb_str_new(mrb, name->base, name->len), mrb_str_new(mrb, value->base, value->len));
- }
- }
-
- { /* headers */
- h2o_header_t **headers_sorted = alloca(sizeof(*headers_sorted) * generator->req->headers.size);
- size_t i;
- for (i = 0; i != generator->req->headers.size; ++i)
- headers_sorted[i] = generator->req->headers.entries + i;
- qsort(headers_sorted, generator->req->headers.size, sizeof(*headers_sorted), build_env_sort_header_cb);
- for (i = 0; i != generator->req->headers.size; ++i) {
- const h2o_header_t *header = headers_sorted[i];
- mrb_value n, v;
- if (h2o_iovec_is_token(header->name)) {
- const h2o_token_t *token = H2O_STRUCT_FROM_MEMBER(h2o_token_t, buf, header->name);
- if (token == H2O_TOKEN_TRANSFER_ENCODING)
- continue;
- n = mrb_ary_entry(shared->constants, (mrb_int)(token - h2o__tokens));
- } else {
- h2o_iovec_t vec = convert_header_name_to_env(&generator->req->pool, header->name->base, header->name->len);
- n = mrb_str_new(mrb, vec.base, vec.len);
- }
- v = mrb_str_new(mrb, header->value.base, header->value.len);
- while (i < generator->req->headers.size - 1) {
- if (!h2o_memis(headers_sorted[i + 1]->name->base, headers_sorted[i + 1]->name->len, header->name->base,
- header->name->len))
- break;
- header = headers_sorted[++i];
- v = mrb_str_append(mrb, v, mrb_ary_entry(shared->constants,
- header->name == &H2O_TOKEN_COOKIE->buf ? H2O_MRUBY_LIT_SEPARATOR_SEMICOLON
- : H2O_MRUBY_LIT_SEPARATOR_COMMA));
- v = mrb_str_append(mrb, v, mrb_str_new(mrb, header->value.base, header->value.len));
- }
- mrb_hash_set(mrb, env, n, v);
- }
- }
-
- /* rack.* */
- /* TBD rack.version? */
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_RACK_URL_SCHEME),
- mrb_str_new(mrb, generator->req->scheme->name.base, generator->req->scheme->name.len));
- /* we are using shared-none architecture, and therefore declare ourselves as multiprocess */
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_RACK_MULTITHREAD), mrb_false_value());
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_RACK_MULTIPROCESS), mrb_true_value());
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_RACK_RUN_ONCE), mrb_false_value());
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_RACK_HIJACK_), mrb_false_value());
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_RACK_ERRORS),
- mrb_gv_get(mrb, mrb_intern_lit(mrb, "$stderr")));
-
- /* server name */
- mrb_hash_set(mrb, env, mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_SERVER_SOFTWARE),
- mrb_ary_entry(shared->constants, H2O_MRUBY_LIT_SERVER_SOFTWARE_VALUE));
-
- return env;
-}
-
-static int handle_response_header(h2o_mruby_context_t *handler_ctx, h2o_iovec_t name, h2o_iovec_t value, void *_req)
-{
- h2o_req_t *req = _req;
- const h2o_token_t *token;
- static const h2o_iovec_t fallthru_set_prefix = {H2O_STRLIT(FALLTHRU_SET_PREFIX)};
-
- /* convert name to lowercase */
- name = h2o_strdup(&req->pool, name.base, name.len);
- h2o_strtolower(name.base, name.len);
-
- if ((token = h2o_lookup_token(name.base, name.len)) != NULL) {
- if (token->proxy_should_drop_for_res) {
- /* skip */
- } else if (token == H2O_TOKEN_CONTENT_LENGTH) {
- req->res.content_length = h2o_strtosize(value.base, value.len);
- } else {
- value = h2o_strdup(&req->pool, value.base, value.len);
- if (token == H2O_TOKEN_LINK) {
- h2o_iovec_t new_value = h2o_push_path_in_link_header(req, value.base, value.len);
- if (new_value.len)
- h2o_add_header(&req->pool, &req->res.headers, token, NULL, new_value.base, new_value.len);
- } else {
- h2o_add_header(&req->pool, &req->res.headers, token, NULL, value.base, value.len);
- }
- }
- } else if (name.len > fallthru_set_prefix.len &&
- h2o_memis(name.base, fallthru_set_prefix.len, fallthru_set_prefix.base, fallthru_set_prefix.len)) {
- /* register environment variables (with the name converted to uppercase, and using `_`) */
- size_t i;
- name.base += fallthru_set_prefix.len;
- name.len -= fallthru_set_prefix.len;
- for (i = 0; i != name.len; ++i)
- name.base[i] = name.base[i] == '-' ? '_' : h2o_toupper(name.base[i]);
- h2o_iovec_t *slot = h2o_req_getenv(req, name.base, name.len, 1);
- *slot = h2o_strdup(&req->pool, value.base, value.len);
- } else {
- value = h2o_strdup(&req->pool, value.base, value.len);
- h2o_add_header_by_str(&req->pool, &req->res.headers, name.base, name.len, 0, NULL, value.base, value.len);
- }
-
- return 0;
-}
-
-static void clear_rack_input(h2o_mruby_generator_t *generator)
-{
- if (!mrb_nil_p(generator->rack_input))
- mrb_input_stream_set_data(generator->ctx->shared->mrb, generator->rack_input, NULL, -1, 0, NULL, NULL);
-}
-
-static void on_generator_dispose(void *_generator)
-{
- h2o_mruby_generator_t *generator = _generator;
-
- clear_rack_input(generator);
- generator->req = NULL;
-
- if (generator->chunked != NULL)
- h2o_mruby_send_chunked_dispose(generator);
-}
-
-static int on_req(h2o_handler_t *_handler, h2o_req_t *req)
-{
- h2o_mruby_handler_t *handler = (void *)_handler;
- h2o_mruby_shared_context_t *shared = get_shared_context(req->conn->ctx);
- int gc_arena = mrb_gc_arena_save(shared->mrb);
-
- h2o_mruby_generator_t *generator = h2o_mem_alloc_shared(&req->pool, sizeof(*generator), on_generator_dispose);
- generator->super.proceed = NULL;
- generator->super.stop = NULL;
- generator->req = req;
- generator->ctx = h2o_context_get_handler_context(req->conn->ctx, &handler->super);
- generator->rack_input = mrb_nil_value();
- generator->chunked = NULL;
-
- mrb_value env = build_env(generator);
-
- int is_delegate = 0;
- h2o_mruby_run_fiber(generator, generator->ctx->proc, env, &is_delegate);
-
- mrb_gc_arena_restore(shared->mrb, gc_arena);
- if (is_delegate)
- return -1;
- return 0;
-}
-
-static void send_response(h2o_mruby_generator_t *generator, mrb_int status, mrb_value resp, int *is_delegate)
-{
- mrb_state *mrb = generator->ctx->shared->mrb;
- mrb_value body;
- h2o_iovec_t content = {NULL};
-
- /* set status */
- generator->req->res.status = (int)status;
-
- /* set headers */
- if (h2o_mruby_iterate_headers(generator->ctx, mrb_ary_entry(resp, 1), handle_response_header, generator->req) != 0) {
- assert(mrb->exc != NULL);
- goto GotException;
- }
-
- /* return without processing body, if status is fallthru */
- if (generator->req->res.status == STATUS_FALLTHRU) {
- if (is_delegate != NULL)
- *is_delegate = 1;
- else
- h2o_delegate_request_deferred(generator->req, &generator->ctx->handler->super);
- return;
- }
-
- /* obtain body */
- body = mrb_ary_entry(resp, 2);
-
- /* flatten body if possible */
- if (mrb_array_p(body)) {
- mrb_int i, len = RARRAY_LEN(body);
- /* calculate the length of the output, while at the same time converting the elements of the output array to string */
- content.len = 0;
- for (i = 0; i != len; ++i) {
- mrb_value e = mrb_ary_entry(body, i);
- if (!mrb_string_p(e)) {
- e = h2o_mruby_to_str(mrb, e);
- if (mrb->exc != NULL)
- goto GotException;
- mrb_ary_set(mrb, body, i, e);
- }
- content.len += RSTRING_LEN(e);
- }
- /* allocate memory, and copy the response */
- char *dst = content.base = h2o_mem_alloc_pool(&generator->req->pool, content.len);
- for (i = 0; i != len; ++i) {
- mrb_value e = mrb_ary_entry(body, i);
- assert(mrb_string_p(e));
- memcpy(dst, RSTRING_PTR(e), RSTRING_LEN(e));
- dst += RSTRING_LEN(e);
- }
- /* reset body to nil, now that we have read all data */
- body = mrb_nil_value();
- }
-
- /* use fiber in case we need to call #each */
- if (!mrb_nil_p(body)) {
- h2o_start_response(generator->req, &generator->super);
- mrb_value receiver = h2o_mruby_send_chunked_init(generator, body);
- if (!mrb_nil_p(receiver))
- h2o_mruby_run_fiber(generator, receiver, body, 0);
- return;
- }
-
- /* send the entire response immediately */
- if (status == 101 || status == 204 || status == 304 ||
- h2o_memis(generator->req->input.method.base, generator->req->input.method.len, H2O_STRLIT("HEAD"))) {
- h2o_start_response(generator->req, &generator->super);
- h2o_send(generator->req, NULL, 0, H2O_SEND_STATE_FINAL);
- } else {
- if (content.len < generator->req->res.content_length) {
- generator->req->res.content_length = content.len;
- } else {
- content.len = generator->req->res.content_length;
- }
- h2o_start_response(generator->req, &generator->super);
- h2o_send(generator->req, &content, 1, H2O_SEND_STATE_FINAL);
- }
- return;
-
-GotException:
- report_exception(generator->req, mrb);
- h2o_send_error_500(generator->req, "Internal Server Error", "Internal Server Error", 0);
-}
-
-void h2o_mruby_run_fiber(h2o_mruby_generator_t *generator, mrb_value receiver, mrb_value input, int *is_delegate)
-{
- mrb_state *mrb = generator->ctx->shared->mrb;
- mrb_value output;
- mrb_int status;
-
- if (!mrb_obj_eq(mrb, generator->ctx->proc, receiver)) {
- mrb_gc_unregister(mrb, receiver);
- mrb_gc_protect(mrb, receiver);
- }
-
- h2o_mruby_current_generator = generator;
-
- while (1) {
- /* send input to fiber */
- output = mrb_funcall_argv(mrb, receiver, generator->ctx->shared->symbols.sym_call, 1, &input);
- if (mrb->exc != NULL)
- goto GotException;
- if (!mrb_array_p(output)) {
- mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "rack app did not return an array"));
- goto GotException;
- }
- /* fetch status */
- mrb_value v = mrb_to_int(mrb, mrb_ary_entry(output, 0));
- if (mrb->exc != NULL)
- goto GotException;
- status = mrb_fixnum(v);
- /* take special action depending on the status code */
- if (status < 0) {
- if (status == H2O_MRUBY_CALLBACK_ID_EXCEPTION_RAISED) {
- mrb->exc = mrb_obj_ptr(mrb_ary_entry(output, 1));
- goto GotException;
- }
- receiver = mrb_ary_entry(output, 1);
- int next_action = H2O_MRUBY_CALLBACK_NEXT_ACTION_IMMEDIATE;
- mrb_value args = mrb_ary_entry(output, 2);
- if (mrb_array_p(args)) {
- switch (status) {
- case H2O_MRUBY_CALLBACK_ID_SEND_CHUNKED_EOS:
- input = h2o_mruby_send_chunked_eos_callback(generator, receiver, args, &next_action);
- break;
- case H2O_MRUBY_CALLBACK_ID_HTTP_JOIN_RESPONSE:
- input = h2o_mruby_http_join_response_callback(generator, receiver, args, &next_action);
- break;
- case H2O_MRUBY_CALLBACK_ID_HTTP_FETCH_CHUNK:
- input = h2o_mruby_http_fetch_chunk_callback(generator, receiver, args, &next_action);
- break;
- default:
- input = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "unexpected callback id sent from rack app");
- break;
- }
- } else {
- input = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "callback from rack app did not receive an array arg");
- }
- switch (next_action) {
- case H2O_MRUBY_CALLBACK_NEXT_ACTION_STOP:
- return;
- case H2O_MRUBY_CALLBACK_NEXT_ACTION_ASYNC:
- goto Async;
- default:
- assert(next_action == H2O_MRUBY_CALLBACK_NEXT_ACTION_IMMEDIATE);
- break;
- }
- goto Next;
- }
- /* if no special actions were necessary, then the output is a rack response */
- break;
- Next:
- mrb_gc_protect(mrb, receiver);
- mrb_gc_protect(mrb, input);
- }
-
- h2o_mruby_current_generator = NULL;
-
- if (!(100 <= status && status <= 999)) {
- mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "status returned from rack app is out of range"));
- goto GotException;
- }
-
- /* send the response (unless req is already closed) */
- if (generator->req == NULL)
- return;
- if (generator->req->_generator != NULL) {
- mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "unexpectedly received a rack response"));
- goto GotException;
- }
- send_response(generator, status, output, is_delegate);
- return;
-
-GotException:
- h2o_mruby_current_generator = NULL;
- if (generator->req != NULL) {
- report_exception(generator->req, mrb);
- if (generator->req->_generator == NULL) {
- h2o_send_error_500(generator->req, "Internal Server Error", "Internal Server Error", 0);
- } else {
- h2o_mruby_send_chunked_close(generator);
- }
- }
- return;
-
-Async:
- h2o_mruby_current_generator = NULL;
- if (!mrb_obj_eq(mrb, generator->ctx->proc, receiver))
- mrb_gc_register(mrb, receiver);
- return;
-}
-
-h2o_mruby_handler_t *h2o_mruby_register(h2o_pathconf_t *pathconf, h2o_mruby_config_vars_t *vars)
-{
- h2o_mruby_handler_t *handler = (void *)h2o_create_handler(pathconf, sizeof(*handler));
-
- handler->super.on_context_init = on_context_init;
- handler->super.on_context_dispose = on_context_dispose;
- handler->super.dispose = on_handler_dispose;
- handler->super.on_req = on_req;
- handler->config.source = h2o_strdup(NULL, vars->source.base, vars->source.len);
- if (vars->path != NULL)
- handler->config.path = h2o_strdup(NULL, vars->path, SIZE_MAX).base;
- handler->config.lineno = vars->lineno;
-
- return handler;
-}
-
-mrb_value h2o_mruby_each_to_array(h2o_mruby_context_t *handler_ctx, mrb_value src)
-{
- return mrb_funcall_argv(handler_ctx->shared->mrb, mrb_ary_entry(handler_ctx->shared->constants, H2O_MRUBY_PROC_EACH_TO_ARRAY),
- handler_ctx->shared->symbols.sym_call, 1, &src);
-}
-
-static int iterate_headers_handle_pair(h2o_mruby_context_t *handler_ctx, mrb_value name, mrb_value value,
- int (*cb)(h2o_mruby_context_t *, h2o_iovec_t, h2o_iovec_t, void *), void *cb_data)
-{
- mrb_state *mrb = handler_ctx->shared->mrb;
-
- /* convert name and value to string */
- name = h2o_mruby_to_str(mrb, name);
- if (mrb->exc != NULL)
- return -1;
- value = h2o_mruby_to_str(mrb, value);
- if (mrb->exc != NULL)
- return -1;
-
- /* call the callback, splitting the values with '\n' */
- const char *vstart = RSTRING_PTR(value), *vend = vstart + RSTRING_LEN(value), *eol;
- while (1) {
- for (eol = vstart; eol != vend; ++eol)
- if (*eol == '\n')
- break;
- if (cb(handler_ctx, h2o_iovec_init(RSTRING_PTR(name), RSTRING_LEN(name)), h2o_iovec_init(vstart, eol - vstart), cb_data) !=
- 0)
- return -1;
- if (eol == vend)
- break;
- vstart = eol + 1;
- }
-
- return 0;
-}
-
-int h2o_mruby_iterate_headers(h2o_mruby_context_t *handler_ctx, mrb_value headers,
- int (*cb)(h2o_mruby_context_t *, h2o_iovec_t, h2o_iovec_t, void *), void *cb_data)
-{
- mrb_state *mrb = handler_ctx->shared->mrb;
-
- if (!(mrb_hash_p(headers) || mrb_array_p(headers))) {
- headers = h2o_mruby_each_to_array(handler_ctx, headers);
- if (mrb->exc != NULL)
- return -1;
- assert(mrb_array_p(headers));
- }
-
- if (mrb_hash_p(headers)) {
- mrb_value keys = mrb_hash_keys(mrb, headers);
- mrb_int i, len = RARRAY_LEN(keys);
- for (i = 0; i != len; ++i) {
- mrb_value k = mrb_ary_entry(keys, i);
- mrb_value v = mrb_hash_get(mrb, headers, k);
- if (iterate_headers_handle_pair(handler_ctx, k, v, cb, cb_data) != 0)
- return -1;
- }
- } else {
- assert(mrb_array_p(headers));
- mrb_int i, len = RARRAY_LEN(headers);
- for (i = 0; i != len; ++i) {
- mrb_value pair = mrb_ary_entry(headers, i);
- if (!mrb_array_p(pair)) {
- mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_ARGUMENT_ERROR, "array element of headers MUST by an array"));
- return -1;
- }
- if (iterate_headers_handle_pair(handler_ctx, mrb_ary_entry(pair, 0), mrb_ary_entry(pair, 1), cb, cb_data) != 0)
- return -1;
- }
- }
-
- return 0;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/mruby/chunked.c b/web/server/h2o/libh2o/lib/handler/mruby/chunked.c
deleted file mode 100644
index 28e3ae433..000000000
--- a/web/server/h2o/libh2o/lib/handler/mruby/chunked.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2015-2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <stdlib.h>
-#include <mruby.h>
-#include <mruby/array.h>
-#include <mruby/error.h>
-#include <mruby/string.h>
-#include "h2o/mruby_.h"
-#include "embedded.c.h"
-
-struct st_h2o_mruby_chunked_t {
- h2o_doublebuffer_t sending;
- size_t bytes_left; /* SIZE_MAX indicates that the number is undermined */
- enum { H2O_MRUBY_CHUNKED_TYPE_CALLBACK, H2O_MRUBY_CHUNKED_TYPE_SHORTCUT } type;
- union {
- struct {
- h2o_buffer_t *receiving;
- mrb_value body_obj; /* becomes nil on eos */
- } callback;
- struct {
- h2o_mruby_http_request_context_t *client;
- h2o_buffer_t *remaining;
- } shortcut;
- };
-};
-
-static void do_send(h2o_mruby_generator_t *generator, h2o_buffer_t **input, int is_final)
-{
- h2o_mruby_chunked_t *chunked = generator->chunked;
-
- assert(chunked->sending.bytes_inflight == 0);
-
- h2o_iovec_t buf = h2o_doublebuffer_prepare(&chunked->sending, input, generator->req->preferred_chunk_size);
- size_t bufcnt = 1;
-
- if (is_final && buf.len == chunked->sending.buf->size && (*input)->size == 0) {
- if (buf.len == 0)
- --bufcnt;
- /* terminate the H1 connection if the length of content served did not match the value sent in content-length header */
- if (chunked->bytes_left != SIZE_MAX && chunked->bytes_left != 0)
- generator->req->http1_is_persistent = 0;
- } else {
- if (buf.len == 0)
- return;
- is_final = 0;
- }
-
- h2o_send(generator->req, &buf, bufcnt, is_final ? H2O_SEND_STATE_FINAL : H2O_SEND_STATE_IN_PROGRESS);
-}
-
-static void do_proceed(h2o_generator_t *_generator, h2o_req_t *req)
-{
- h2o_mruby_generator_t *generator = (void *)_generator;
- h2o_mruby_chunked_t *chunked = generator->chunked;
- h2o_buffer_t **input;
- int is_final;
-
- h2o_doublebuffer_consume(&chunked->sending);
-
- switch (chunked->type) {
- case H2O_MRUBY_CHUNKED_TYPE_CALLBACK:
- input = &chunked->callback.receiving;
- is_final = mrb_nil_p(chunked->callback.body_obj);
- break;
- case H2O_MRUBY_CHUNKED_TYPE_SHORTCUT:
- if (chunked->shortcut.client != NULL) {
- input = h2o_mruby_http_peek_content(chunked->shortcut.client, &is_final);
- assert(!is_final);
- } else {
- input = &chunked->shortcut.remaining;
- is_final = 1;
- }
- break;
- default:
- h2o_fatal("unexpected type");
- break;
- }
-
- do_send(generator, input, is_final);
-}
-
-static void on_shortcut_notify(h2o_mruby_generator_t *generator)
-{
- h2o_mruby_chunked_t *chunked = generator->chunked;
- int is_final;
- h2o_buffer_t **input = h2o_mruby_http_peek_content(chunked->shortcut.client, &is_final);
-
- if (chunked->bytes_left != SIZE_MAX) {
- if (chunked->bytes_left < (*input)->size)
- (*input)->size = chunked->bytes_left; /* trim data too long */
- chunked->bytes_left -= (*input)->size;
- }
-
- /* if final, steal socket input buffer to shortcut.remaining, and reset pointer to client */
- if (is_final) {
- chunked->shortcut.remaining = *input;
- h2o_buffer_init(input, &h2o_socket_buffer_prototype);
- input = &chunked->shortcut.remaining;
- chunked->shortcut.client = NULL;
- }
-
- if (chunked->sending.bytes_inflight == 0)
- do_send(generator, input, is_final);
-}
-
-static void close_body_obj(h2o_mruby_generator_t *generator)
-{
- h2o_mruby_chunked_t *chunked = generator->chunked;
- mrb_state *mrb = generator->ctx->shared->mrb;
-
- if (!mrb_nil_p(chunked->callback.body_obj)) {
- /* call close and throw away error */
- if (mrb_respond_to(mrb, chunked->callback.body_obj, generator->ctx->shared->symbols.sym_close))
- mrb_funcall_argv(mrb, chunked->callback.body_obj, generator->ctx->shared->symbols.sym_close, 0, NULL);
- mrb->exc = NULL;
- mrb_gc_unregister(mrb, chunked->callback.body_obj);
- chunked->callback.body_obj = mrb_nil_value();
- }
-}
-
-mrb_value h2o_mruby_send_chunked_init(h2o_mruby_generator_t *generator, mrb_value body)
-{
- h2o_mruby_chunked_t *chunked = h2o_mem_alloc_pool(&generator->req->pool, sizeof(*chunked));
- h2o_doublebuffer_init(&chunked->sending, &h2o_socket_buffer_prototype);
- chunked->bytes_left = h2o_memis(generator->req->method.base, generator->req->method.len, H2O_STRLIT("HEAD"))
- ? 0
- : generator->req->res.content_length;
- generator->super.proceed = do_proceed;
- generator->chunked = chunked;
-
- if ((chunked->shortcut.client = h2o_mruby_http_set_shortcut(generator->ctx->shared->mrb, body, on_shortcut_notify)) != NULL) {
- chunked->type = H2O_MRUBY_CHUNKED_TYPE_SHORTCUT;
- chunked->shortcut.remaining = NULL;
- on_shortcut_notify(generator);
- return mrb_nil_value();
- } else {
- chunked->type = H2O_MRUBY_CHUNKED_TYPE_CALLBACK;
- h2o_buffer_init(&chunked->callback.receiving, &h2o_socket_buffer_prototype);
- mrb_gc_register(generator->ctx->shared->mrb, body);
- chunked->callback.body_obj = body;
- return mrb_ary_entry(generator->ctx->shared->constants, H2O_MRUBY_CHUNKED_PROC_EACH_TO_FIBER);
- }
-}
-
-void h2o_mruby_send_chunked_dispose(h2o_mruby_generator_t *generator)
-{
- h2o_mruby_chunked_t *chunked = generator->chunked;
-
- h2o_doublebuffer_dispose(&chunked->sending);
-
- switch (chunked->type) {
- case H2O_MRUBY_CHUNKED_TYPE_CALLBACK:
- h2o_buffer_dispose(&chunked->callback.receiving);
- close_body_obj(generator);
- break;
- case H2O_MRUBY_CHUNKED_TYPE_SHORTCUT:
- /* note: no need to free reference from chunked->client, since it is disposed at the same moment */
- if (chunked->shortcut.remaining != NULL)
- h2o_buffer_dispose(&chunked->shortcut.remaining);
- break;
- }
-}
-
-static mrb_value check_precond(mrb_state *mrb, h2o_mruby_generator_t *generator)
-{
- if (generator == NULL || generator->req == NULL)
- return mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "downstream HTTP closed");
- if (generator->req->_generator == NULL)
- return mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "cannot send chunk before sending headers");
- return mrb_nil_value();
-}
-
-static mrb_value send_chunked_method(mrb_state *mrb, mrb_value self)
-{
- h2o_mruby_generator_t *generator = h2o_mruby_current_generator;
- const char *s;
- mrb_int len;
-
- /* parse args */
- mrb_get_args(mrb, "s", &s, &len);
-
- { /* precond check */
- mrb_value exc = check_precond(mrb, generator);
- if (!mrb_nil_p(exc))
- mrb_exc_raise(mrb, exc);
- }
-
- /* append to send buffer, and send out immediately if necessary */
- if (len != 0) {
- h2o_mruby_chunked_t *chunked = generator->chunked;
- if (chunked->bytes_left != SIZE_MAX) {
- if (len > chunked->bytes_left)
- len = chunked->bytes_left;
- chunked->bytes_left -= len;
- }
- if (len != 0) {
- h2o_buffer_reserve(&chunked->callback.receiving, len);
- memcpy(chunked->callback.receiving->bytes + chunked->callback.receiving->size, s, len);
- chunked->callback.receiving->size += len;
- if (chunked->sending.bytes_inflight == 0)
- do_send(generator, &chunked->callback.receiving, 0);
- }
- }
-
- return mrb_nil_value();
-}
-
-mrb_value h2o_mruby_send_chunked_eos_callback(h2o_mruby_generator_t *generator, mrb_value receiver, mrb_value input,
- int *next_action)
-{
- mrb_state *mrb = generator->ctx->shared->mrb;
-
- { /* precond check */
- mrb_value exc = check_precond(mrb, generator);
- if (!mrb_nil_p(exc))
- return exc;
- }
-
- h2o_mruby_send_chunked_close(generator);
-
- *next_action = H2O_MRUBY_CALLBACK_NEXT_ACTION_STOP;
- return mrb_nil_value();
-}
-
-void h2o_mruby_send_chunked_close(h2o_mruby_generator_t *generator)
-{
- h2o_mruby_chunked_t *chunked = generator->chunked;
-
- /* run_fiber will never be called once we enter the fast path, and therefore this function will never get called in that case */
- assert(chunked->type == H2O_MRUBY_CHUNKED_TYPE_CALLBACK);
-
- close_body_obj(generator);
-
- if (chunked->sending.bytes_inflight == 0)
- do_send(generator, &chunked->callback.receiving, 1);
-}
-
-void h2o_mruby_send_chunked_init_context(h2o_mruby_shared_context_t *shared_ctx)
-{
- mrb_state *mrb = shared_ctx->mrb;
-
- h2o_mruby_eval_expr(mrb, H2O_MRUBY_CODE_CHUNKED);
- h2o_mruby_assert(mrb);
-
- mrb_define_method(mrb, mrb->kernel_module, "_h2o_send_chunk", send_chunked_method, MRB_ARGS_ARG(1, 0));
- h2o_mruby_define_callback(mrb, "_h2o_send_chunk_eos", H2O_MRUBY_CALLBACK_ID_SEND_CHUNKED_EOS);
-
- mrb_ary_set(mrb, shared_ctx->constants, H2O_MRUBY_CHUNKED_PROC_EACH_TO_FIBER,
- mrb_funcall(mrb, mrb_top_self(mrb), "_h2o_chunked_proc_each_to_fiber", 0));
- h2o_mruby_assert(mrb);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/mruby/embedded.c.h b/web/server/h2o/libh2o/lib/handler/mruby/embedded.c.h
deleted file mode 100644
index db4bb2321..000000000
--- a/web/server/h2o/libh2o/lib/handler/mruby/embedded.c.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * DO NOT EDIT! generated by embed_mruby_code.pl
- * Please refer to the respective source files for copyright information.
- */
-
-/* lib/handler/mruby/embedded/core.rb */
-#define H2O_MRUBY_CODE_CORE \
- "module Kernel\n" \
- " def _h2o_define_callback(name, id)\n" \
- " Kernel.define_method(name) do |*args|\n" \
- " ret = Fiber.yield([ id, _h2o_create_resumer(), args ])\n" \
- " if ret.kind_of? Exception\n" \
- " raise ret\n" \
- " end\n" \
- " ret\n" \
- " end\n" \
- " end\n" \
- " def _h2o_create_resumer()\n" \
- " me = Fiber.current\n" \
- " Proc.new do |v|\n" \
- " me.resume(v)\n" \
- " end\n" \
- " end\n" \
- " def _h2o_proc_each_to_array()\n" \
- " Proc.new do |o|\n" \
- " a = []\n" \
- " o.each do |x|\n" \
- " a << x\n" \
- " end\n" \
- " a\n" \
- " end\n" \
- " end\n" \
- " def _h2o_proc_app_to_fiber()\n" \
- " Proc.new do |app|\n" \
- " cached = nil\n" \
- " Proc.new do |req|\n" \
- " fiber = cached\n" \
- " cached = nil\n" \
- " if !fiber\n" \
- " fiber = Fiber.new do\n" \
- " self_fiber = Fiber.current\n" \
- " req = Fiber.yield\n" \
- " while 1\n" \
- " begin\n" \
- " while 1\n" \
- " resp = app.call(req)\n" \
- " cached = self_fiber\n" \
- " req = Fiber.yield(resp)\n" \
- " end\n" \
- " rescue => e\n" \
- " cached = self_fiber\n" \
- " req = Fiber.yield([-1, e])\n" \
- " end\n" \
- " end\n" \
- " end\n" \
- " fiber.resume\n" \
- " end\n" \
- " fiber.resume(req)\n" \
- " end\n" \
- " end\n" \
- " end\n" \
- "end\n"
-
-/* lib/handler/mruby/embedded/http_request.rb */
-#define H2O_MRUBY_CODE_HTTP_REQUEST \
- "module H2O\n" \
- " class HttpRequest\n" \
- " def join\n" \
- " if !@resp\n" \
- " @resp = _h2o__http_join_response(self)\n" \
- " end\n" \
- " @resp\n" \
- " end\n" \
- " def _set_response(resp)\n" \
- " @resp = resp\n" \
- " end\n" \
- " end\n" \
- " class HttpInputStream\n" \
- " def each\n" \
- " while c = _h2o__http_fetch_chunk(self)\n" \
- " yield c\n" \
- " end\n" \
- " end\n" \
- " def join\n" \
- " s = \"\"\n" \
- " each do |c|\n" \
- " s << c\n" \
- " end\n" \
- " s\n" \
- " end\n" \
- " class Empty < HttpInputStream\n" \
- " def each; end\n" \
- " end\n" \
- " end\n" \
- "end\n"
-
-/* lib/handler/mruby/embedded/chunked.rb */
-#define H2O_MRUBY_CODE_CHUNKED \
- "module Kernel\n" \
- " def _h2o_chunked_proc_each_to_fiber()\n" \
- " Proc.new do |src|\n" \
- " fiber = Fiber.new do\n" \
- " src.each do |chunk|\n" \
- " _h2o_send_chunk(chunk)\n" \
- " end\n" \
- " _h2o_send_chunk_eos()\n" \
- " end\n" \
- " fiber.resume\n" \
- " end\n" \
- " end\n" \
- "end\n"
diff --git a/web/server/h2o/libh2o/lib/handler/mruby/embedded/chunked.rb b/web/server/h2o/libh2o/lib/handler/mruby/embedded/chunked.rb
deleted file mode 100644
index ff4e578f8..000000000
--- a/web/server/h2o/libh2o/lib/handler/mruby/embedded/chunked.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# 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.
-
-module Kernel
-
- def _h2o_chunked_proc_each_to_fiber()
- Proc.new do |src|
- fiber = Fiber.new do
- src.each do |chunk|
- _h2o_send_chunk(chunk)
- end
- _h2o_send_chunk_eos()
- end
- fiber.resume
- end
- end
-
-end
diff --git a/web/server/h2o/libh2o/lib/handler/mruby/embedded/core.rb b/web/server/h2o/libh2o/lib/handler/mruby/embedded/core.rb
deleted file mode 100644
index e62583df4..000000000
--- a/web/server/h2o/libh2o/lib/handler/mruby/embedded/core.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Ryosuke Matsumoto,
-# Masayoshi Takahashi
-#
-# 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.
-
-module Kernel
-
- def _h2o_define_callback(name, id)
- Kernel.define_method(name) do |*args|
- ret = Fiber.yield([ id, _h2o_create_resumer(), args ])
- if ret.kind_of? Exception
- raise ret
- end
- ret
- end
- end
-
- def _h2o_create_resumer()
- me = Fiber.current
- Proc.new do |v|
- me.resume(v)
- end
- end
-
- def _h2o_proc_each_to_array()
- Proc.new do |o|
- a = []
- o.each do |x|
- a << x
- end
- a
- end
- end
-
- def _h2o_proc_app_to_fiber()
- Proc.new do |app|
- cached = nil
- Proc.new do |req|
- fiber = cached
- cached = nil
- if !fiber
- fiber = Fiber.new do
- self_fiber = Fiber.current
- req = Fiber.yield
- while 1
- begin
- while 1
- resp = app.call(req)
- cached = self_fiber
- req = Fiber.yield(resp)
- end
- rescue => e
- cached = self_fiber
- req = Fiber.yield([-1, e])
- end
- end
- end
- fiber.resume
- end
- fiber.resume(req)
- end
- end
- end
-
-end
diff --git a/web/server/h2o/libh2o/lib/handler/mruby/embedded/http_request.rb b/web/server/h2o/libh2o/lib/handler/mruby/embedded/http_request.rb
deleted file mode 100644
index 3f3247a3c..000000000
--- a/web/server/h2o/libh2o/lib/handler/mruby/embedded/http_request.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (c) 2015-2016 DeNA Co., Ltd., Kazuho Oku
-#
-# 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.
-
-module H2O
-
- class HttpRequest
- def join
- if !@resp
- @resp = _h2o__http_join_response(self)
- end
- @resp
- end
- def _set_response(resp)
- @resp = resp
- end
- end
-
- class HttpInputStream
- def each
- while c = _h2o__http_fetch_chunk(self)
- yield c
- end
- end
- def join
- s = ""
- each do |c|
- s << c
- end
- s
- end
-
- class Empty < HttpInputStream
- def each; end
- end
- end
-
-end
diff --git a/web/server/h2o/libh2o/lib/handler/mruby/http_request.c b/web/server/h2o/libh2o/lib/handler/mruby/http_request.c
deleted file mode 100644
index 964d03f19..000000000
--- a/web/server/h2o/libh2o/lib/handler/mruby/http_request.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * Copyright (c) 2015-2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <mruby.h>
-#include <mruby/array.h>
-#include <mruby/error.h>
-#include <mruby/hash.h>
-#include <mruby/string.h>
-#include <mruby_input_stream.h>
-#include "h2o/mruby_.h"
-#include "embedded.c.h"
-
-struct st_h2o_mruby_http_request_context_t {
- h2o_mruby_generator_t *generator;
- h2o_http1client_t *client;
- mrb_value receiver;
- struct {
- h2o_buffer_t *buf;
- h2o_iovec_t body; /* body.base != NULL indicates that post content exists (and the length MAY be zero) */
- unsigned method_is_head : 1;
- unsigned has_transfer_encoding : 1;
- } req;
- struct {
- h2o_buffer_t *after_closed; /* when client becomes NULL, rest of the data will be stored to this pointer */
- int has_content;
- } resp;
- struct {
- mrb_value request;
- mrb_value input_stream;
- } refs;
- void (*shortcut_notify_cb)(h2o_mruby_generator_t *generator);
-};
-
-static void on_gc_dispose_request(mrb_state *mrb, void *_ctx)
-{
- struct st_h2o_mruby_http_request_context_t *ctx = _ctx;
- if (ctx != NULL)
- ctx->refs.request = mrb_nil_value();
-}
-
-const static struct mrb_data_type request_type = {"http_request", on_gc_dispose_request};
-
-static void on_gc_dispose_input_stream(mrb_state *mrb, void *_ctx)
-{
- struct st_h2o_mruby_http_request_context_t *ctx = _ctx;
- if (ctx != NULL)
- ctx->refs.input_stream = mrb_nil_value();
-}
-
-const static struct mrb_data_type input_stream_type = {"http_input_stream", on_gc_dispose_input_stream};
-
-static mrb_value create_downstream_closed_exception(mrb_state *mrb)
-{
- return mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "downstream HTTP closed");
-}
-
-static mrb_value detach_receiver(struct st_h2o_mruby_http_request_context_t *ctx)
-{
- mrb_value ret = ctx->receiver;
- assert(!mrb_nil_p(ret));
- ctx->receiver = mrb_nil_value();
- return ret;
-}
-
-static void on_dispose(void *_ctx)
-{
- struct st_h2o_mruby_http_request_context_t *ctx = _ctx;
-
- /* clear the refs */
- if (ctx->client != NULL) {
- h2o_http1client_cancel(ctx->client);
- ctx->client = NULL;
- }
- if (!mrb_nil_p(ctx->refs.request))
- DATA_PTR(ctx->refs.request) = NULL;
- if (!mrb_nil_p(ctx->refs.input_stream))
- DATA_PTR(ctx->refs.input_stream) = NULL;
-
- /* clear bufs */
- h2o_buffer_dispose(&ctx->req.buf);
- h2o_buffer_dispose(&ctx->resp.after_closed);
-
- /* notify the app, if it is waiting to hear from us */
- if (!mrb_nil_p(ctx->receiver)) {
- mrb_state *mrb = ctx->generator->ctx->shared->mrb;
- int gc_arena = mrb_gc_arena_save(mrb);
- h2o_mruby_run_fiber(ctx->generator, detach_receiver(ctx), create_downstream_closed_exception(mrb), NULL);
- mrb_gc_arena_restore(mrb, gc_arena);
- }
-}
-
-static void post_response(struct st_h2o_mruby_http_request_context_t *ctx, int status, const h2o_header_t *headers_sorted,
- size_t num_headers)
-{
- mrb_state *mrb = ctx->generator->ctx->shared->mrb;
- int gc_arena = mrb_gc_arena_save(mrb);
- size_t i;
-
- mrb_value resp = mrb_ary_new_capa(mrb, 3);
-
- /* set status */
- mrb_ary_set(mrb, resp, 0, mrb_fixnum_value(status));
-
- /* set headers */
- mrb_value headers_hash = mrb_hash_new_capa(mrb, (int)num_headers);
- for (i = 0; i < num_headers; ++i) {
- /* skip the headers, we determine the eos! */
- if (h2o_memis(headers_sorted[i].name, headers_sorted[i].name->len, H2O_STRLIT("content-length")) ||
- h2o_memis(headers_sorted[i].name, headers_sorted[i].name->len, H2O_STRLIT("transfer-encoding")))
- continue;
- /* build and set the hash entry */
- mrb_value k = mrb_str_new(mrb, headers_sorted[i].name->base, headers_sorted[i].name->len);
- mrb_value v = mrb_str_new(mrb, headers_sorted[i].value.base, headers_sorted[i].value.len);
- while (i + 1 < num_headers && h2o_memis(headers_sorted[i].name->base, headers_sorted[i].name->len,
- headers_sorted[i + 1].name->base, headers_sorted[i + 1].name->len)) {
- ++i;
- v = mrb_str_cat_lit(mrb, v, "\n");
- v = mrb_str_cat(mrb, v, headers_sorted[i].value.base, headers_sorted[i].value.len);
- }
- mrb_hash_set(mrb, headers_hash, k, v);
- }
- mrb_ary_set(mrb, resp, 1, headers_hash);
-
- /* set input stream */
- assert(mrb_nil_p(ctx->refs.input_stream));
- mrb_value input_stream_class;
- if (ctx->req.method_is_head || status == 101 || status == 204 || status == 304) {
- input_stream_class = mrb_ary_entry(ctx->generator->ctx->shared->constants, H2O_MRUBY_HTTP_EMPTY_INPUT_STREAM_CLASS);
- } else {
- input_stream_class = mrb_ary_entry(ctx->generator->ctx->shared->constants, H2O_MRUBY_HTTP_INPUT_STREAM_CLASS);
- }
- ctx->refs.input_stream = h2o_mruby_create_data_instance(mrb, input_stream_class, ctx, &input_stream_type);
- mrb_ary_set(mrb, resp, 2, ctx->refs.input_stream);
-
- if (mrb_nil_p(ctx->receiver)) {
- /* is async */
- mrb_funcall(mrb, ctx->refs.request, "_set_response", 1, resp);
- if (mrb->exc != NULL) {
- fprintf(stderr, "_set_response failed\n");
- abort();
- }
- } else {
- /* send response to the waiting receiver */
- h2o_mruby_run_fiber(ctx->generator, detach_receiver(ctx), resp, NULL);
- }
-
- mrb_gc_arena_restore(mrb, gc_arena);
-}
-
-static void post_error(struct st_h2o_mruby_http_request_context_t *ctx, const char *errstr)
-{
- static const h2o_header_t headers_sorted[] = {
- {&H2O_TOKEN_CONTENT_TYPE->buf, NULL, {H2O_STRLIT("text/plain; charset=utf-8")}},
- };
-
- ctx->client = NULL;
- size_t errstr_len = strlen(errstr);
- h2o_buffer_reserve(&ctx->resp.after_closed, errstr_len);
- memcpy(ctx->resp.after_closed->bytes + ctx->resp.after_closed->size, errstr, errstr_len);
- ctx->resp.after_closed->size += errstr_len;
- ctx->resp.has_content = 1;
-
- post_response(ctx, 500, headers_sorted, sizeof(headers_sorted) / sizeof(headers_sorted[0]));
-}
-
-static mrb_value build_chunk(struct st_h2o_mruby_http_request_context_t *ctx)
-{
- mrb_value chunk;
-
- assert(ctx->resp.has_content);
-
- if (ctx->client != NULL) {
- assert(ctx->client->sock->input->size != 0);
- chunk = mrb_str_new(ctx->generator->ctx->shared->mrb, ctx->client->sock->input->bytes, ctx->client->sock->input->size);
- h2o_buffer_consume(&ctx->client->sock->input, ctx->client->sock->input->size);
- ctx->resp.has_content = 0;
- } else {
- if (ctx->resp.after_closed->size == 0) {
- chunk = mrb_nil_value();
- } else {
- chunk = mrb_str_new(ctx->generator->ctx->shared->mrb, ctx->resp.after_closed->bytes, ctx->resp.after_closed->size);
- h2o_buffer_consume(&ctx->resp.after_closed, ctx->resp.after_closed->size);
- }
- /* has_content is retained as true, so that repeated calls will return nil immediately */
- }
-
- return chunk;
-}
-
-static int on_body(h2o_http1client_t *client, const char *errstr)
-{
- struct st_h2o_mruby_http_request_context_t *ctx = client->data;
-
- if (errstr != NULL) {
- h2o_buffer_t *tmp = ctx->resp.after_closed;
- ctx->resp.after_closed = client->sock->input;
- client->sock->input = tmp;
- ctx->client = NULL;
- ctx->resp.has_content = 1;
- } else if (client->sock->input->size != 0) {
- ctx->resp.has_content = 1;
- }
-
- if (ctx->resp.has_content) {
- if (ctx->shortcut_notify_cb != NULL) {
- ctx->shortcut_notify_cb(ctx->generator);
- } else if (!mrb_nil_p(ctx->receiver)) {
- int gc_arena = mrb_gc_arena_save(ctx->generator->ctx->shared->mrb);
- mrb_value chunk = build_chunk(ctx);
- h2o_mruby_run_fiber(ctx->generator, detach_receiver(ctx), chunk, NULL);
- mrb_gc_arena_restore(ctx->generator->ctx->shared->mrb, gc_arena);
- }
- }
- return 0;
-}
-
-static int headers_sort_cb(const void *_x, const void *_y)
-{
- const h2o_header_t *x = _x, *y = _y;
-
- if (x->name->len < y->name->len)
- return -1;
- if (x->name->len > y->name->len)
- return 1;
- return memcmp(x->name->base, y->name->base, x->name->len);
-}
-
-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, int rlen)
-{
- struct st_h2o_mruby_http_request_context_t *ctx = client->data;
-
- if (errstr != NULL) {
- if (errstr != h2o_http1client_error_is_eos) {
- /* error */
- post_error(ctx, errstr);
- return NULL;
- }
- /* closed without body */
- ctx->client = NULL;
- }
-
- qsort(headers, num_headers, sizeof(headers[0]), headers_sort_cb);
- post_response(ctx, status, headers, num_headers);
- return on_body;
-}
-
-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)
-{
- struct st_h2o_mruby_http_request_context_t *ctx = client->data;
-
- if (errstr != NULL) {
- post_error(ctx, errstr);
- return NULL;
- }
-
- *reqbufs = h2o_mem_alloc_pool(&ctx->generator->req->pool, sizeof(**reqbufs) * 2);
- **reqbufs = h2o_iovec_init(ctx->req.buf->bytes, ctx->req.buf->size);
- *reqbufcnt = 1;
- if (ctx->req.body.base != NULL)
- (*reqbufs)[(*reqbufcnt)++] = ctx->req.body;
- *method_is_head = ctx->req.method_is_head;
- return on_head;
-}
-
-static inline void append_to_buffer(h2o_buffer_t **buf, const void *src, size_t len)
-{
- memcpy((*buf)->bytes + (*buf)->size, src, len);
- (*buf)->size += len;
-}
-
-static int flatten_request_header(h2o_mruby_context_t *handler_ctx, h2o_iovec_t name, h2o_iovec_t value, void *_ctx)
-{
- struct st_h2o_mruby_http_request_context_t *ctx = _ctx;
-
- /* ignore certain headers */
- if (h2o_lcstris(name.base, name.len, H2O_STRLIT("content-length")) ||
- h2o_lcstris(name.base, name.len, H2O_STRLIT("connection")) || h2o_lcstris(name.base, name.len, H2O_STRLIT("host")))
- return 0;
-
- /* mark the existence of transfer-encoding in order to prevent us from adding content-length header */
- if (h2o_lcstris(name.base, name.len, H2O_STRLIT("transfer-encoding")))
- ctx->req.has_transfer_encoding = 1;
-
- h2o_buffer_reserve(&ctx->req.buf, name.len + value.len + sizeof(": \r\n") - 1);
- append_to_buffer(&ctx->req.buf, name.base, name.len);
- append_to_buffer(&ctx->req.buf, H2O_STRLIT(": "));
- append_to_buffer(&ctx->req.buf, value.base, value.len);
- append_to_buffer(&ctx->req.buf, H2O_STRLIT("\r\n"));
-
- return 0;
-}
-
-static mrb_value http_request_method(mrb_state *mrb, mrb_value self)
-{
- h2o_mruby_generator_t *generator;
- struct st_h2o_mruby_http_request_context_t *ctx;
- const char *arg_url;
- mrb_int arg_url_len;
- mrb_value arg_hash;
- h2o_iovec_t method;
- h2o_url_t url;
-
- /* parse args */
- arg_hash = mrb_nil_value();
- mrb_get_args(mrb, "s|H", &arg_url, &arg_url_len, &arg_hash);
-
- /* precond check */
- if ((generator = h2o_mruby_current_generator) == NULL || generator->req == NULL)
- mrb_exc_raise(mrb, create_downstream_closed_exception(mrb));
-
- /* allocate context and initialize */
- ctx = h2o_mem_alloc_shared(&generator->req->pool, sizeof(*ctx), on_dispose);
- memset(ctx, 0, sizeof(*ctx));
- ctx->generator = generator;
- ctx->receiver = mrb_nil_value();
- h2o_buffer_init(&ctx->req.buf, &h2o_socket_buffer_prototype);
- h2o_buffer_init(&ctx->resp.after_closed, &h2o_socket_buffer_prototype);
- ctx->refs.request = mrb_nil_value();
- ctx->refs.input_stream = mrb_nil_value();
-
- /* uri */
- if (h2o_url_parse(arg_url, arg_url_len, &url) != 0)
- mrb_raise(mrb, E_ARGUMENT_ERROR, "invaild URL");
-
- /* method */
- method = h2o_iovec_init(H2O_STRLIT("GET"));
- if (mrb_hash_p(arg_hash)) {
- mrb_value t = mrb_hash_get(mrb, arg_hash, mrb_symbol_value(generator->ctx->shared->symbols.sym_method));
- if (!mrb_nil_p(t)) {
- t = mrb_str_to_str(mrb, t);
- method = h2o_iovec_init(RSTRING_PTR(t), RSTRING_LEN(t));
- if (h2o_memis(method.base, method.len, H2O_STRLIT("HEAD"))) {
- ctx->req.method_is_head = 1;
- }
- }
- }
-
- /* start building the request */
- h2o_buffer_reserve(&ctx->req.buf, method.len + 1);
- append_to_buffer(&ctx->req.buf, method.base, method.len);
- append_to_buffer(&ctx->req.buf, H2O_STRLIT(" "));
- h2o_buffer_reserve(&ctx->req.buf,
- url.path.len + url.authority.len + sizeof(" HTTP/1.1\r\nConnection: close\r\nHost: \r\n") - 1);
- append_to_buffer(&ctx->req.buf, url.path.base, url.path.len);
- append_to_buffer(&ctx->req.buf, H2O_STRLIT(" HTTP/1.1\r\nConnection: close\r\nHost: "));
- append_to_buffer(&ctx->req.buf, url.authority.base, url.authority.len);
- append_to_buffer(&ctx->req.buf, H2O_STRLIT("\r\n"));
-
- /* headers */
- if (mrb_hash_p(arg_hash)) {
- mrb_value headers = mrb_hash_get(mrb, arg_hash, mrb_symbol_value(generator->ctx->shared->symbols.sym_headers));
- if (!mrb_nil_p(headers)) {
- if (h2o_mruby_iterate_headers(generator->ctx, headers, flatten_request_header, ctx) != 0) {
- mrb_value exc = mrb_obj_value(mrb->exc);
- mrb->exc = NULL;
- mrb_exc_raise(mrb, exc);
- }
- }
- }
- /* body */
- if (mrb_hash_p(arg_hash)) {
- mrb_value body = mrb_hash_get(mrb, arg_hash, mrb_symbol_value(generator->ctx->shared->symbols.sym_body));
- if (!mrb_nil_p(body)) {
- if (mrb_obj_eq(mrb, body, generator->rack_input)) {
- /* fast path */
- mrb_int pos;
- mrb_input_stream_get_data(mrb, body, NULL, NULL, &pos, NULL, NULL);
- ctx->req.body = generator->req->entity;
- ctx->req.body.base += pos;
- ctx->req.body.len -= pos;
- } else {
- if (!mrb_string_p(body)) {
- body = mrb_funcall(mrb, body, "read", 0);
- if (!mrb_string_p(body))
- mrb_raise(mrb, E_ARGUMENT_ERROR, "body.read did not return string");
- }
- ctx->req.body = h2o_strdup(&ctx->generator->req->pool, RSTRING_PTR(body), RSTRING_LEN(body));
- }
- if (!ctx->req.has_transfer_encoding) {
- char buf[64];
- size_t l = (size_t)sprintf(buf, "content-length: %zu\r\n", ctx->req.body.len);
- h2o_buffer_reserve(&ctx->req.buf, l);
- append_to_buffer(&ctx->req.buf, buf, l);
- }
- }
- }
-
- h2o_buffer_reserve(&ctx->req.buf, 2);
- append_to_buffer(&ctx->req.buf, H2O_STRLIT("\r\n"));
-
- /* build request and connect */
- ctx->refs.request = h2o_mruby_create_data_instance(
- mrb, mrb_ary_entry(generator->ctx->shared->constants, H2O_MRUBY_HTTP_REQUEST_CLASS), ctx, &request_type);
- h2o_http1client_connect(&ctx->client, ctx, &generator->req->conn->ctx->proxy.client_ctx, url.host, h2o_url_get_port(&url),
- url.scheme == &H2O_URL_SCHEME_HTTPS, on_connect);
-
- return ctx->refs.request;
-}
-
-mrb_value h2o_mruby_http_join_response_callback(h2o_mruby_generator_t *generator, mrb_value receiver, mrb_value args,
- int *next_action)
-{
- mrb_state *mrb = generator->ctx->shared->mrb;
- struct st_h2o_mruby_http_request_context_t *ctx;
-
- if (generator->req == NULL)
- return create_downstream_closed_exception(mrb);
-
- if ((ctx = mrb_data_check_get_ptr(mrb, mrb_ary_entry(args, 0), &request_type)) == NULL)
- return mrb_exc_new_str_lit(mrb, E_ARGUMENT_ERROR, "HttpRequest#join wrong self");
-
- ctx->receiver = receiver;
- *next_action = H2O_MRUBY_CALLBACK_NEXT_ACTION_ASYNC;
- return mrb_nil_value();
-}
-
-mrb_value h2o_mruby_http_fetch_chunk_callback(h2o_mruby_generator_t *generator, mrb_value receiver, mrb_value args,
- int *next_action)
-{
- mrb_state *mrb = generator->ctx->shared->mrb;
- struct st_h2o_mruby_http_request_context_t *ctx;
- mrb_value ret;
-
- if (generator->req == NULL)
- return create_downstream_closed_exception(mrb);
-
- if ((ctx = mrb_data_check_get_ptr(mrb, mrb_ary_entry(args, 0), &input_stream_type)) == NULL)
- return mrb_exc_new_str_lit(mrb, E_ARGUMENT_ERROR, "_HttpInputStream#each wrong self");
-
- if (ctx->resp.has_content) {
- ret = build_chunk(ctx);
- } else {
- ctx->receiver = receiver;
- *next_action = H2O_MRUBY_CALLBACK_NEXT_ACTION_ASYNC;
- ret = mrb_nil_value();
- }
-
- return ret;
-}
-
-h2o_mruby_http_request_context_t *h2o_mruby_http_set_shortcut(mrb_state *mrb, mrb_value obj, void (*cb)(h2o_mruby_generator_t *))
-{
- struct st_h2o_mruby_http_request_context_t *ctx;
-
- if ((ctx = mrb_data_check_get_ptr(mrb, obj, &input_stream_type)) == NULL)
- return NULL;
- ctx->shortcut_notify_cb = cb;
- return ctx;
-}
-
-h2o_buffer_t **h2o_mruby_http_peek_content(h2o_mruby_http_request_context_t *ctx, int *is_final)
-{
- *is_final = ctx->client == NULL;
- return ctx->client != NULL && ctx->resp.has_content ? &ctx->client->sock->input : &ctx->resp.after_closed;
-}
-
-void h2o_mruby_http_request_init_context(h2o_mruby_shared_context_t *ctx)
-{
- mrb_state *mrb = ctx->mrb;
-
- h2o_mruby_eval_expr(mrb, H2O_MRUBY_CODE_HTTP_REQUEST);
- h2o_mruby_assert(mrb);
-
- struct RClass *module, *klass;
- module = mrb_define_module(mrb, "H2O");
-
- mrb_define_method(mrb, mrb->kernel_module, "http_request", http_request_method, MRB_ARGS_ARG(1, 2));
-
- klass = mrb_class_get_under(mrb, module, "HttpRequest");
- mrb_ary_set(mrb, ctx->constants, H2O_MRUBY_HTTP_REQUEST_CLASS, mrb_obj_value(klass));
-
- klass = mrb_class_get_under(mrb, module, "HttpInputStream");
- mrb_ary_set(mrb, ctx->constants, H2O_MRUBY_HTTP_INPUT_STREAM_CLASS, mrb_obj_value(klass));
-
- klass = mrb_class_get_under(mrb, klass, "Empty");
- mrb_ary_set(mrb, ctx->constants, H2O_MRUBY_HTTP_EMPTY_INPUT_STREAM_CLASS, mrb_obj_value(klass));
-
- h2o_mruby_define_callback(mrb, "_h2o__http_join_response", H2O_MRUBY_CALLBACK_ID_HTTP_JOIN_RESPONSE);
- h2o_mruby_define_callback(mrb, "_h2o__http_fetch_chunk", H2O_MRUBY_CALLBACK_ID_HTTP_FETCH_CHUNK);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/proxy.c b/web/server/h2o/libh2o/lib/handler/proxy.c
deleted file mode 100644
index 1d87225e1..000000000
--- a/web/server/h2o/libh2o/lib/handler/proxy.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2014,2015 DeNA Co., Ltd., Masahiro Nagano
- *
- * 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 <sys/un.h>
-#include "h2o.h"
-#include "h2o/socketpool.h"
-
-struct rp_handler_t {
- h2o_handler_t super;
- h2o_url_t upstream; /* host should be NULL-terminated */
- h2o_socketpool_t *sockpool; /* non-NULL if config.use_keepalive == 1 */
- h2o_proxy_config_vars_t config;
-};
-
-static int on_req(h2o_handler_t *_self, h2o_req_t *req)
-{
- struct rp_handler_t *self = (void *)_self;
- h2o_req_overrides_t *overrides = h2o_mem_alloc_pool(&req->pool, sizeof(*overrides));
- const h2o_url_scheme_t *scheme;
- h2o_iovec_t *authority;
-
- /* setup overrides */
- *overrides = (h2o_req_overrides_t){NULL};
- if (self->sockpool != NULL) {
- overrides->socketpool = self->sockpool;
- } else if (self->config.preserve_host) {
- overrides->hostport.host = self->upstream.host;
- overrides->hostport.port = h2o_url_get_port(&self->upstream);
- }
- overrides->location_rewrite.match = &self->upstream;
- overrides->location_rewrite.path_prefix = req->pathconf->path;
- overrides->use_proxy_protocol = self->config.use_proxy_protocol;
- overrides->client_ctx = h2o_context_get_handler_context(req->conn->ctx, &self->super);
- overrides->headers_cmds = self->config.headers_cmds;
-
- /* determine the scheme and authority */
- if (self->config.preserve_host) {
- scheme = req->scheme;
- authority = &req->authority;
- } else {
- scheme = self->upstream.scheme;
- authority = &self->upstream.authority;
- }
-
- /* request reprocess */
- h2o_reprocess_request(req, req->method, scheme, *authority,
- h2o_build_destination(req, self->upstream.path.base, self->upstream.path.len, 0), overrides, 0);
-
- return 0;
-}
-
-static void on_context_init(h2o_handler_t *_self, h2o_context_t *ctx)
-{
- struct rp_handler_t *self = (void *)_self;
-
- /* use the loop of first context for handling socketpool timeouts */
- if (self->sockpool != NULL && self->sockpool->timeout == UINT64_MAX)
- h2o_socketpool_set_timeout(self->sockpool, ctx->loop, self->config.keepalive_timeout);
-
- /* setup a specific client context only if we need to */
- if (ctx->globalconf->proxy.io_timeout == self->config.io_timeout && !self->config.websocket.enabled &&
- self->config.ssl_ctx == ctx->globalconf->proxy.ssl_ctx)
- return;
-
- h2o_http1client_ctx_t *client_ctx = h2o_mem_alloc(sizeof(*ctx));
- client_ctx->loop = ctx->loop;
- client_ctx->getaddr_receiver = &ctx->receivers.hostinfo_getaddr;
- if (ctx->globalconf->proxy.io_timeout == self->config.io_timeout) {
- client_ctx->io_timeout = &ctx->proxy.io_timeout;
- } else {
- client_ctx->io_timeout = h2o_mem_alloc(sizeof(*client_ctx->io_timeout));
- h2o_timeout_init(client_ctx->loop, client_ctx->io_timeout, self->config.io_timeout);
- }
- if (self->config.websocket.enabled) {
- /* FIXME avoid creating h2o_timeout_t for every path-level context in case the timeout values are the same */
- client_ctx->websocket_timeout = h2o_mem_alloc(sizeof(*client_ctx->websocket_timeout));
- h2o_timeout_init(client_ctx->loop, client_ctx->websocket_timeout, self->config.websocket.timeout);
- } else {
- client_ctx->websocket_timeout = NULL;
- }
- client_ctx->ssl_ctx = self->config.ssl_ctx;
-
- h2o_context_set_handler_context(ctx, &self->super, client_ctx);
-}
-
-static void on_context_dispose(h2o_handler_t *_self, h2o_context_t *ctx)
-{
- struct rp_handler_t *self = (void *)_self;
- h2o_http1client_ctx_t *client_ctx = h2o_context_get_handler_context(ctx, &self->super);
-
- if (client_ctx == NULL)
- return;
-
- if (client_ctx->io_timeout != &ctx->proxy.io_timeout) {
- h2o_timeout_dispose(client_ctx->loop, client_ctx->io_timeout);
- free(client_ctx->io_timeout);
- }
- if (client_ctx->websocket_timeout != NULL) {
- h2o_timeout_dispose(client_ctx->loop, client_ctx->websocket_timeout);
- free(client_ctx->websocket_timeout);
- }
- free(client_ctx);
-}
-
-static void on_handler_dispose(h2o_handler_t *_self)
-{
- struct rp_handler_t *self = (void *)_self;
-
- if (self->config.ssl_ctx != NULL)
- SSL_CTX_free(self->config.ssl_ctx);
- free(self->upstream.host.base);
- free(self->upstream.path.base);
- if (self->sockpool != NULL) {
- h2o_socketpool_dispose(self->sockpool);
- free(self->sockpool);
- }
-}
-
-void h2o_proxy_register_reverse_proxy(h2o_pathconf_t *pathconf, h2o_url_t *upstream, h2o_proxy_config_vars_t *config)
-{
- struct sockaddr_un sa;
- const char *to_sa_err;
- struct rp_handler_t *self = (void *)h2o_create_handler(pathconf, sizeof(*self));
- self->super.on_context_init = on_context_init;
- self->super.on_context_dispose = on_context_dispose;
- self->super.dispose = on_handler_dispose;
- self->super.on_req = on_req;
- to_sa_err = h2o_url_host_to_sun(upstream->host, &sa);
- if (config->keepalive_timeout != 0) {
- self->sockpool = h2o_mem_alloc(sizeof(*self->sockpool));
- int is_ssl = upstream->scheme == &H2O_URL_SCHEME_HTTPS;
- if (to_sa_err == h2o_url_host_to_sun_err_is_not_unix_socket) {
- h2o_socketpool_init_by_hostport(self->sockpool, upstream->host, h2o_url_get_port(upstream), is_ssl,
- SIZE_MAX /* FIXME */);
- } else {
- assert(to_sa_err == NULL);
- h2o_socketpool_init_by_address(self->sockpool, (void *)&sa, sizeof(sa), is_ssl, SIZE_MAX /* FIXME */);
- }
- }
- h2o_url_copy(NULL, &self->upstream, upstream);
- if (to_sa_err) {
- h2o_strtolower(self->upstream.host.base, self->upstream.host.len);
- }
- self->config = *config;
- if (self->config.ssl_ctx != NULL)
- SSL_CTX_up_ref(self->config.ssl_ctx);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/redirect.c b/web/server/h2o/libh2o/lib/handler/redirect.c
deleted file mode 100644
index c8b9c5086..000000000
--- a/web/server/h2o/libh2o/lib/handler/redirect.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <stdlib.h>
-#include "h2o.h"
-
-#define MODULE_NAME "lib/handler/redirect.c"
-
-struct st_h2o_redirect_handler_t {
- h2o_handler_t super;
- int internal;
- int status;
- h2o_iovec_t prefix;
-};
-
-static void on_dispose(h2o_handler_t *_self)
-{
- h2o_redirect_handler_t *self = (void *)_self;
- free(self->prefix.base);
-}
-
-static void redirect_internally(h2o_redirect_handler_t *self, h2o_req_t *req, h2o_iovec_t dest)
-{
- h2o_iovec_t method;
- h2o_url_t input, resolved;
-
- /* resolve the URL */
- if (h2o_url_parse_relative(dest.base, dest.len, &input) != 0) {
- h2o_req_log_error(req, MODULE_NAME, "invalid destination:%.*s", (int)dest.len, dest.base);
- goto SendInternalError;
- }
- if (input.scheme != NULL && input.authority.base != NULL) {
- resolved = input;
- } else {
- h2o_url_t base;
- /* we MUST to set authority to that of hostconf, or internal redirect might create a TCP connection */
- if (h2o_url_init(&base, req->scheme, req->hostconf->authority.hostport, req->path) != 0) {
- h2o_req_log_error(req, MODULE_NAME, "failed to parse current authority:%.*s", (int)req->authority.len,
- req->authority.base);
- goto SendInternalError;
- }
- h2o_url_resolve(&req->pool, &base, &input, &resolved);
- }
-
- /* determine the method */
- switch (self->status) {
- case 307:
- case 308:
- method = req->method;
- break;
- default:
- method = h2o_iovec_init(H2O_STRLIT("GET"));
- req->entity = (h2o_iovec_t){NULL};
- break;
- }
-
- h2o_reprocess_request_deferred(req, method, resolved.scheme, resolved.authority, resolved.path, NULL, 1);
- return;
-
-SendInternalError:
- h2o_send_error_503(req, "Internal Server Error", "internal server error", 0);
-}
-
-static int on_req(h2o_handler_t *_self, h2o_req_t *req)
-{
- h2o_redirect_handler_t *self = (void *)_self;
- h2o_iovec_t dest = h2o_build_destination(req, self->prefix.base, self->prefix.len, 1);
-
- /* redirect */
- if (self->internal) {
- redirect_internally(self, req, dest);
- } else {
- h2o_send_redirect(req, self->status, "Redirected", dest.base, dest.len);
- }
-
- return 0;
-}
-
-h2o_redirect_handler_t *h2o_redirect_register(h2o_pathconf_t *pathconf, int internal, int status, const char *prefix)
-{
- h2o_redirect_handler_t *self = (void *)h2o_create_handler(pathconf, sizeof(*self));
- self->super.dispose = on_dispose;
- self->super.on_req = on_req;
- self->internal = internal;
- self->status = status;
- self->prefix = h2o_strdup(NULL, prefix, SIZE_MAX);
- return self;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/reproxy.c b/web/server/h2o/libh2o/lib/handler/reproxy.c
deleted file mode 100644
index 369386d27..000000000
--- a/web/server/h2o/libh2o/lib/handler/reproxy.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2014,2015 DeNA Co., Ltd., Kazuho Oku, Daisuke Maki
- *
- * 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 "h2o.h"
-
-static void on_send(h2o_ostream_t *self, h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state)
-{
- /* nothing to do */
-}
-
-static void on_setup_ostream(h2o_filter_t *self, h2o_req_t *req, h2o_ostream_t **slot)
-{
- h2o_iovec_t dest, method;
- ssize_t xru_index;
-
- /* obtain x-reproxy-url header, or skip to next ostream */
- if ((xru_index = h2o_find_header(&req->res.headers, H2O_TOKEN_X_REPROXY_URL, -1)) == -1) {
- h2o_setup_next_ostream(req, slot);
- return;
- }
- dest = req->res.headers.entries[xru_index].value;
- h2o_delete_header(&req->res.headers, xru_index);
-
- /* setup params */
- switch (req->res.status) {
- case 307:
- case 308:
- method = req->method;
- break;
- default:
- method = h2o_iovec_init(H2O_STRLIT("GET"));
- req->entity = (h2o_iovec_t){NULL};
- break;
- }
-
- /* request internal redirect (is deferred) */
- h2o_send_redirect_internal(req, method, dest.base, dest.len, 0);
-
- /* setup filter (that swallows the response until the timeout gets fired) */
- h2o_ostream_t *ostream = h2o_add_ostream(req, sizeof(*ostream), slot);
- ostream->do_send = on_send;
-}
-
-void h2o_reproxy_register(h2o_pathconf_t *pathconf)
-{
- h2o_filter_t *self = h2o_create_filter(pathconf, sizeof(*self));
- self->on_setup_ostream = on_setup_ostream;
-}
diff --git a/web/server/h2o/libh2o/lib/handler/status.c b/web/server/h2o/libh2o/lib/handler/status.c
deleted file mode 100644
index 93befed3b..000000000
--- a/web/server/h2o/libh2o/lib/handler/status.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 "h2o.h"
-
-extern h2o_status_handler_t events_status_handler;
-extern h2o_status_handler_t requests_status_handler;
-extern h2o_status_handler_t durations_status_handler;
-
-struct st_h2o_status_logger_t {
- h2o_logger_t super;
-};
-
-struct st_h2o_root_status_handler_t {
- h2o_handler_t super;
- H2O_VECTOR(h2o_multithread_receiver_t *) receivers;
-};
-
-struct st_h2o_status_context_t {
- h2o_context_t *ctx;
- h2o_multithread_receiver_t receiver;
-};
-
-struct st_status_ctx_t {
- int active;
- void *ctx;
-};
-struct st_h2o_status_collector_t {
- struct {
- h2o_req_t *req;
- h2o_multithread_receiver_t *receiver;
- } src;
- size_t num_remaining_threads_atomic;
- H2O_VECTOR(struct st_status_ctx_t) status_ctx;
-};
-
-struct st_h2o_status_message_t {
- h2o_multithread_message_t super;
- struct st_h2o_status_collector_t *collector;
-};
-
-static void collect_reqs_of_context(struct st_h2o_status_collector_t *collector, h2o_context_t *ctx)
-{
- int i;
-
- for (i = 0; i < ctx->globalconf->statuses.size; i++) {
- struct st_status_ctx_t *sc = collector->status_ctx.entries + i;
- h2o_status_handler_t *sh = ctx->globalconf->statuses.entries + i;
- if (sc->active && sh->per_thread != NULL)
- sh->per_thread(sc->ctx, ctx);
- }
-
- if (__sync_sub_and_fetch(&collector->num_remaining_threads_atomic, 1) == 0) {
- struct st_h2o_status_message_t *message = h2o_mem_alloc(sizeof(*message));
- message->super = (h2o_multithread_message_t){{NULL}};
- message->collector = collector;
- h2o_multithread_send_message(collector->src.receiver, &message->super);
- }
-}
-
-static void send_response(struct st_h2o_status_collector_t *collector)
-{
- static h2o_generator_t generator = {NULL, NULL};
- h2o_req_t *req;
- size_t nr_statuses;
- int i;
- int cur_resp = 0;
-
- req = collector->src.req;
- if (!req) {
- h2o_mem_release_shared(collector);
- return;
- }
-
- nr_statuses = req->conn->ctx->globalconf->statuses.size;
- size_t nr_resp = nr_statuses + 2; // 2 for the footer and header
- h2o_iovec_t resp[nr_resp];
-
- memset(resp, 0, sizeof(resp[0]) * nr_resp);
- resp[cur_resp++] = (h2o_iovec_t){H2O_STRLIT("{\n")};
-
- int coma_removed = 0;
- for (i = 0; i < req->conn->ctx->globalconf->statuses.size; i++) {
- h2o_status_handler_t *sh = &req->conn->ctx->globalconf->statuses.entries[i];
- if (!collector->status_ctx.entries[i].active) {
- continue;
- }
- resp[cur_resp++] = sh->final(collector->status_ctx.entries[i].ctx, req->conn->ctx->globalconf, req);
- if (resp[cur_resp - 1].len > 0 && !coma_removed) {
- /* requests come in with a leading coma, replace if with a space */
- resp[cur_resp - 1].base[0] = ' ';
- coma_removed = 1;
- }
- }
- resp[cur_resp++] = (h2o_iovec_t){H2O_STRLIT("\n}\n")};
-
- req->res.status = 200;
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CONTENT_TYPE, NULL, H2O_STRLIT("text/plain; charset=utf-8"));
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CACHE_CONTROL, NULL, H2O_STRLIT("no-cache, no-store"));
- h2o_start_response(req, &generator);
- h2o_send(req, resp, h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("HEAD")) ? 0 : nr_resp,
- H2O_SEND_STATE_FINAL);
- h2o_mem_release_shared(collector);
-}
-
-static void on_collect_notify(h2o_multithread_receiver_t *receiver, h2o_linklist_t *messages)
-{
- struct st_h2o_status_context_t *status_ctx = H2O_STRUCT_FROM_MEMBER(struct st_h2o_status_context_t, receiver, receiver);
-
- while (!h2o_linklist_is_empty(messages)) {
- struct st_h2o_status_message_t *message = H2O_STRUCT_FROM_MEMBER(struct st_h2o_status_message_t, super, messages->next);
- struct st_h2o_status_collector_t *collector = message->collector;
- h2o_linklist_unlink(&message->super.link);
- free(message);
-
- if (__sync_add_and_fetch(&collector->num_remaining_threads_atomic, 0) != 0) {
- collect_reqs_of_context(collector, status_ctx->ctx);
- } else {
- send_response(collector);
- }
- }
-}
-
-static void on_collector_dispose(void *_collector)
-{
-}
-
-static void on_req_close(void *p)
-{
- struct st_h2o_status_collector_t *collector = *(void **)p;
- collector->src.req = NULL;
- h2o_mem_release_shared(collector);
-}
-
-static int on_req_json(struct st_h2o_root_status_handler_t *self, h2o_req_t *req, h2o_iovec_t status_list)
-{
- { /* construct collector and send request to every thread */
- struct st_h2o_status_context_t *status_ctx = h2o_context_get_handler_context(req->conn->ctx, &self->super);
- struct st_h2o_status_collector_t *collector = h2o_mem_alloc_shared(NULL, sizeof(*collector), on_collector_dispose);
- size_t i;
-
- memset(collector, 0, sizeof(*collector));
- for (i = 0; i < req->conn->ctx->globalconf->statuses.size; i++) {
- h2o_status_handler_t *sh;
-
- h2o_vector_reserve(&req->pool, &collector->status_ctx, collector->status_ctx.size + 1);
- sh = &req->conn->ctx->globalconf->statuses.entries[i];
-
- if (status_list.base) {
- if (!h2o_contains_token(status_list.base, status_list.len, sh->name.base, sh->name.len, ',')) {
- collector->status_ctx.entries[collector->status_ctx.size].active = 0;
- goto Skip;
- }
- }
- if (sh->init) {
- collector->status_ctx.entries[collector->status_ctx.size].ctx = sh->init();
- }
- collector->status_ctx.entries[collector->status_ctx.size].active = 1;
- Skip:
- collector->status_ctx.size++;
- }
- collector->src.req = req;
- collector->src.receiver = &status_ctx->receiver;
- collector->num_remaining_threads_atomic = self->receivers.size;
-
- for (i = 0; i != self->receivers.size; ++i) {
- struct st_h2o_status_message_t *message = h2o_mem_alloc(sizeof(*message));
- *message = (struct st_h2o_status_message_t){{{NULL}}, collector};
- h2o_multithread_send_message(self->receivers.entries[i], &message->super);
- }
-
- /* collector is also retained by the on_req_close callback */
- *(struct st_h2o_status_collector_t **)h2o_mem_alloc_shared(&req->pool, sizeof(collector), on_req_close) = collector;
- h2o_mem_addref_shared(collector);
- }
-
- return 0;
-}
-
-static int on_req(h2o_handler_t *_self, h2o_req_t *req)
-{
- struct st_h2o_root_status_handler_t *self = (void *)_self;
- size_t prefix_len = req->pathconf->path.len - (req->pathconf->path.base[req->pathconf->path.len - 1] == '/');
- h2o_iovec_t local_path = h2o_iovec_init(req->path_normalized.base + prefix_len, req->path_normalized.len - prefix_len);
-
- if (local_path.len == 0 || h2o_memis(local_path.base, local_path.len, H2O_STRLIT("/"))) {
- /* root of the handler returns HTML that renders the status */
- h2o_iovec_t fn;
- const char *root = getenv("H2O_ROOT");
- if (root == NULL)
- root = H2O_TO_STR(H2O_ROOT);
- fn = h2o_concat(&req->pool, h2o_iovec_init(root, strlen(root)), h2o_iovec_init(H2O_STRLIT("/share/h2o/status/index.html")));
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_CACHE_CONTROL, NULL, H2O_STRLIT("no-cache"));
- return h2o_file_send(req, 200, "OK", fn.base, h2o_iovec_init(H2O_STRLIT("text/html; charset=utf-8")), 0);
- } else if (h2o_memis(local_path.base, local_path.len, H2O_STRLIT("/json"))) {
- int ret;
- /* "/json" maps to the JSON API */
- h2o_iovec_t status_list = {NULL, 0}; /* NULL means we'll show all statuses */
- if (req->query_at != SIZE_MAX && (req->path.len - req->query_at > 6)) {
- if (h2o_memis(&req->path.base[req->query_at], 6, "?show=", 6)) {
- status_list = h2o_iovec_init(&req->path.base[req->query_at + 6], req->path.len - req->query_at - 6);
- }
- }
- ret = on_req_json(self, req, status_list);
- return ret;
- }
-
- return -1;
-}
-
-static void on_context_init(h2o_handler_t *_self, h2o_context_t *ctx)
-{
- struct st_h2o_root_status_handler_t *self = (void *)_self;
- struct st_h2o_status_context_t *status_ctx = h2o_mem_alloc(sizeof(*status_ctx));
-
- status_ctx->ctx = ctx;
- h2o_multithread_register_receiver(ctx->queue, &status_ctx->receiver, on_collect_notify);
-
- h2o_vector_reserve(NULL, &self->receivers, self->receivers.size + 1);
- self->receivers.entries[self->receivers.size++] = &status_ctx->receiver;
-
- h2o_context_set_handler_context(ctx, &self->super, status_ctx);
-}
-
-static void on_context_dispose(h2o_handler_t *_self, h2o_context_t *ctx)
-{
- struct st_h2o_root_status_handler_t *self = (void *)_self;
- struct st_h2o_status_context_t *status_ctx = h2o_context_get_handler_context(ctx, &self->super);
- size_t i;
-
- for (i = 0; i != self->receivers.size; ++i)
- if (self->receivers.entries[i] == &status_ctx->receiver)
- break;
- assert(i != self->receivers.size);
- memmove(self->receivers.entries + i + 1, self->receivers.entries + i, self->receivers.size - i - 1);
- --self->receivers.size;
-
- h2o_multithread_unregister_receiver(ctx->queue, &status_ctx->receiver);
-
- free(status_ctx);
-}
-
-void h2o_status_register(h2o_pathconf_t *conf)
-{
- struct st_h2o_root_status_handler_t *self = (void *)h2o_create_handler(conf, sizeof(*self));
- self->super.on_context_init = on_context_init;
- self->super.on_context_dispose = on_context_dispose;
- self->super.on_req = on_req;
- h2o_config_register_status_handler(conf->global, requests_status_handler);
- h2o_config_register_status_handler(conf->global, events_status_handler);
- h2o_config_register_status_handler(conf->global, durations_status_handler);
-}
diff --git a/web/server/h2o/libh2o/lib/handler/status/durations.c b/web/server/h2o/libh2o/lib/handler/status/durations.c
deleted file mode 100644
index f011107bf..000000000
--- a/web/server/h2o/libh2o/lib/handler/status/durations.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (c) 2016 Fastly
- *
- * 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 "h2o.h"
-#include "gkc.h"
-#include <inttypes.h>
-#include <pthread.h>
-
-#define GK_EPSILON 0.01
-
-struct st_duration_stats_t {
- struct gkc_summary *connect_time;
- struct gkc_summary *header_time;
- struct gkc_summary *body_time;
- struct gkc_summary *request_total_time;
- struct gkc_summary *process_time;
- struct gkc_summary *response_time;
- struct gkc_summary *duration;
-};
-
-struct st_duration_agg_stats_t {
- struct st_duration_stats_t stats;
- pthread_mutex_t mutex;
-};
-
-static h2o_logger_t *durations_logger;
-static void durations_status_per_thread(void *priv, h2o_context_t *ctx)
-{
- struct st_duration_agg_stats_t *agg_stats = priv;
- if (durations_logger) {
- struct st_duration_stats_t *ctx_stats = h2o_context_get_logger_context(ctx, durations_logger);
- pthread_mutex_lock(&agg_stats->mutex);
-#define ADD_DURATION(x) \
- do { \
- struct gkc_summary *tmp; \
- tmp = gkc_combine(agg_stats->stats.x, ctx_stats->x); \
- gkc_summary_free(agg_stats->stats.x); \
- agg_stats->stats.x = tmp; \
- } while (0)
- ADD_DURATION(connect_time);
- ADD_DURATION(header_time);
- ADD_DURATION(body_time);
- ADD_DURATION(request_total_time);
- ADD_DURATION(process_time);
- ADD_DURATION(response_time);
- ADD_DURATION(duration);
-#undef ADD_DURATION
- pthread_mutex_unlock(&agg_stats->mutex);
- }
-}
-
-static void duration_stats_init(struct st_duration_stats_t *stats)
-{
- stats->connect_time = gkc_summary_alloc(GK_EPSILON);
- stats->header_time = gkc_summary_alloc(GK_EPSILON);
- stats->body_time = gkc_summary_alloc(GK_EPSILON);
- stats->request_total_time = gkc_summary_alloc(GK_EPSILON);
- stats->process_time = gkc_summary_alloc(GK_EPSILON);
- stats->response_time = gkc_summary_alloc(GK_EPSILON);
- stats->duration = gkc_summary_alloc(GK_EPSILON);
-}
-
-static void *durations_status_init(void)
-{
- struct st_duration_agg_stats_t *agg_stats;
-
- agg_stats = h2o_mem_alloc(sizeof(*agg_stats));
-
- duration_stats_init(&agg_stats->stats);
- pthread_mutex_init(&agg_stats->mutex, NULL);
-
- return agg_stats;
-}
-
-static void duration_stats_free(struct st_duration_stats_t *stats)
-{
- gkc_summary_free(stats->connect_time);
- gkc_summary_free(stats->header_time);
- gkc_summary_free(stats->body_time);
- gkc_summary_free(stats->request_total_time);
- gkc_summary_free(stats->process_time);
- gkc_summary_free(stats->response_time);
- gkc_summary_free(stats->duration);
-}
-
-static h2o_iovec_t durations_status_final(void *priv, h2o_globalconf_t *gconf, h2o_req_t *req)
-{
- struct st_duration_agg_stats_t *agg_stats = priv;
- h2o_iovec_t ret;
-
-#define BUFSIZE 16384
-#define DURATION_FMT(x) \
- " \"" x "-0\": %lu,\n" \
- " \"" x "-25\": %lu,\n" \
- " \"" x "-50\": %lu,\n" \
- " \"" x "-75\": %lu,\n" \
- " \"" x "-99\": %lu\n"
-#define DURATION_VALS(x) \
- gkc_query(agg_stats->stats.x, 0), gkc_query(agg_stats->stats.x, 0.25), gkc_query(agg_stats->stats.x, 0.5), \
- gkc_query(agg_stats->stats.x, 0.75), gkc_query(agg_stats->stats.x, 0.99)
-
- ret.base = h2o_mem_alloc_pool(&req->pool, BUFSIZE);
- ret.len = snprintf(
- ret.base, BUFSIZE,
- ",\n" DURATION_FMT("connect-time") "," DURATION_FMT("header-time") "," DURATION_FMT("body-time") "," DURATION_FMT(
- "request-total-time") "," DURATION_FMT("process-time") "," DURATION_FMT("response-time") "," DURATION_FMT("duration"),
- DURATION_VALS(connect_time), DURATION_VALS(header_time), DURATION_VALS(body_time), DURATION_VALS(request_total_time),
- DURATION_VALS(process_time), DURATION_VALS(response_time), DURATION_VALS(duration));
-
-#undef BUFSIZE
-#undef DURATION_FMT
-#undef DURATION_VALS
-
- duration_stats_free(&agg_stats->stats);
- pthread_mutex_destroy(&agg_stats->mutex);
-
- free(agg_stats);
- return ret;
-}
-
-static void stat_access(h2o_logger_t *_self, h2o_req_t *req)
-{
- struct st_duration_stats_t *ctx_stats = h2o_context_get_logger_context(req->conn->ctx, _self);
-#define ADD_OBSERVATION(x, from, until) \
- do { \
- int64_t dur; \
- if (h2o_time_compute_##x(req, &dur)) { \
- gkc_insert_value(ctx_stats->x, dur); \
- } \
- } while (0)
-
- ADD_OBSERVATION(connect_time, &req->conn->connected_at, &req->timestamps.request_begin_at);
- ADD_OBSERVATION(header_time, &req->timestamps.request_begin_at, h2o_timeval_is_null(&req->timestamps.request_body_begin_at)
- ? &req->processed_at.at
- : &req->timestamps.request_body_begin_at);
- ADD_OBSERVATION(body_time, h2o_timeval_is_null(&req->timestamps.request_body_begin_at) ? &req->processed_at.at
- : &req->timestamps.request_body_begin_at,
- &req->processed_at.at);
- ADD_OBSERVATION(request_total_time, &req->timestamps.request_begin_at, &req->processed_at.at);
- ADD_OBSERVATION(process_time, &req->processed_at.at, &req->timestamps.response_start_at);
- ADD_OBSERVATION(response_time, &req->timestamps.response_start_at, &req->timestamps.response_end_at);
- ADD_OBSERVATION(duration, &req->timestamps.request_begin_at, &req->timestamps.response_end_at);
-#undef ADD_OBSERVATION
-}
-
-void on_context_init(struct st_h2o_logger_t *self, h2o_context_t *ctx)
-{
- struct st_duration_stats_t *duration_stats = h2o_mem_alloc(sizeof(struct st_duration_stats_t));
- duration_stats_init(duration_stats);
- h2o_context_set_logger_context(ctx, self, duration_stats);
-}
-
-void on_context_dispose(struct st_h2o_logger_t *self, h2o_context_t *ctx)
-{
- struct st_duration_stats_t *duration_stats;
- duration_stats = h2o_context_get_logger_context(ctx, self);
- duration_stats_free(duration_stats);
-}
-
-void h2o_duration_stats_register(h2o_globalconf_t *conf)
-{
- int i, k;
- h2o_logger_t *logger;
- h2o_hostconf_t *hconf;
-
- durations_logger = logger = h2o_mem_alloc(sizeof(*logger));
- memset(logger, 0, sizeof(*logger));
- logger->_config_slot = conf->_num_config_slots++;
- logger->log_access = stat_access;
- logger->on_context_init = on_context_init;
- logger->on_context_dispose = on_context_dispose;
-
- for (k = 0; conf->hosts[k]; k++) {
- hconf = conf->hosts[k];
- for (i = 0; i < hconf->paths.size; i++) {
- int j;
- for (j = 0; j < hconf->paths.entries[i].handlers.size; j++) {
- h2o_pathconf_t *pathconf = &hconf->paths.entries[i];
- h2o_vector_reserve(NULL, &pathconf->loggers, pathconf->loggers.size + 1);
- pathconf->loggers.entries[pathconf->loggers.size++] = (void *)logger;
- }
- }
- }
-}
-
-h2o_status_handler_t durations_status_handler = {
- {H2O_STRLIT("durations")}, durations_status_init, durations_status_per_thread, durations_status_final,
-};
diff --git a/web/server/h2o/libh2o/lib/handler/status/events.c b/web/server/h2o/libh2o/lib/handler/status/events.c
deleted file mode 100644
index e6ed0b7c6..000000000
--- a/web/server/h2o/libh2o/lib/handler/status/events.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2016 Fastly
- *
- * 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 "h2o.h"
-#include <inttypes.h>
-
-struct st_events_status_ctx_t {
- uint64_t emitted_status_errors[H2O_STATUS_ERROR_MAX];
- uint64_t h2_protocol_level_errors[H2O_HTTP2_ERROR_MAX];
- uint64_t h2_read_closed;
- uint64_t h2_write_closed;
- pthread_mutex_t mutex;
-};
-
-static void events_status_per_thread(void *priv, h2o_context_t *ctx)
-{
- size_t i;
- struct st_events_status_ctx_t *esc = priv;
-
- pthread_mutex_lock(&esc->mutex);
-
- for (i = 0; i < H2O_STATUS_ERROR_MAX; i++) {
- esc->emitted_status_errors[i] += ctx->emitted_error_status[i];
- }
- for (i = 0; i < H2O_HTTP2_ERROR_MAX; i++) {
- esc->h2_protocol_level_errors[i] += ctx->http2.events.protocol_level_errors[i];
- }
- esc->h2_read_closed += ctx->http2.events.read_closed;
- esc->h2_write_closed += ctx->http2.events.write_closed;
-
- pthread_mutex_unlock(&esc->mutex);
-}
-
-static void *events_status_init(void)
-{
- struct st_events_status_ctx_t *ret;
-
- ret = h2o_mem_alloc(sizeof(*ret));
- memset(ret, 0, sizeof(*ret));
- pthread_mutex_init(&ret->mutex, NULL);
-
- return ret;
-}
-
-static h2o_iovec_t events_status_final(void *priv, h2o_globalconf_t *gconf, h2o_req_t *req)
-{
- struct st_events_status_ctx_t *esc = priv;
- h2o_iovec_t ret;
-
-#define H1_AGG_ERR(status_) esc->emitted_status_errors[H2O_STATUS_ERROR_##status_]
-#define H2_AGG_ERR(err_) esc->h2_protocol_level_errors[-H2O_HTTP2_ERROR_##err_]
-#define BUFSIZE (2 * 1024)
- ret.base = h2o_mem_alloc_pool(&req->pool, BUFSIZE);
- ret.len = snprintf(ret.base, BUFSIZE, ",\n"
- " \"status-errors.400\": %" PRIu64 ",\n"
- " \"status-errors.403\": %" PRIu64 ",\n"
- " \"status-errors.404\": %" PRIu64 ",\n"
- " \"status-errors.405\": %" PRIu64 ",\n"
- " \"status-errors.416\": %" PRIu64 ",\n"
- " \"status-errors.417\": %" PRIu64 ",\n"
- " \"status-errors.500\": %" PRIu64 ",\n"
- " \"status-errors.502\": %" PRIu64 ",\n"
- " \"status-errors.503\": %" PRIu64 ",\n"
- " \"http2-errors.protocol\": %" PRIu64 ", \n"
- " \"http2-errors.internal\": %" PRIu64 ", \n"
- " \"http2-errors.flow-control\": %" PRIu64 ", \n"
- " \"http2-errors.settings-timeout\": %" PRIu64 ", \n"
- " \"http2-errors.stream-closed\": %" PRIu64 ", \n"
- " \"http2-errors.frame-size\": %" PRIu64 ", \n"
- " \"http2-errors.refused-stream\": %" PRIu64 ", \n"
- " \"http2-errors.cancel\": %" PRIu64 ", \n"
- " \"http2-errors.compression\": %" PRIu64 ", \n"
- " \"http2-errors.connect\": %" PRIu64 ", \n"
- " \"http2-errors.enhance-your-calm\": %" PRIu64 ", \n"
- " \"http2-errors.inadequate-security\": %" PRIu64 ", \n"
- " \"http2.read-closed\": %" PRIu64 ", \n"
- " \"http2.write-closed\": %" PRIu64 "\n",
- H1_AGG_ERR(400), H1_AGG_ERR(403), H1_AGG_ERR(404), H1_AGG_ERR(405), H1_AGG_ERR(416), H1_AGG_ERR(417),
- H1_AGG_ERR(500), H1_AGG_ERR(502), H1_AGG_ERR(503), H2_AGG_ERR(PROTOCOL), H2_AGG_ERR(INTERNAL),
- H2_AGG_ERR(FLOW_CONTROL), H2_AGG_ERR(SETTINGS_TIMEOUT), H2_AGG_ERR(STREAM_CLOSED), H2_AGG_ERR(FRAME_SIZE),
- H2_AGG_ERR(REFUSED_STREAM), H2_AGG_ERR(CANCEL), H2_AGG_ERR(COMPRESSION), H2_AGG_ERR(CONNECT),
- H2_AGG_ERR(ENHANCE_YOUR_CALM), H2_AGG_ERR(INADEQUATE_SECURITY), esc->h2_read_closed, esc->h2_write_closed);
- pthread_mutex_destroy(&esc->mutex);
- free(esc);
- return ret;
-#undef BUFSIZE
-#undef H1_AGG_ERR
-#undef H2_AGG_ERR
-}
-
-h2o_status_handler_t events_status_handler = {
- {H2O_STRLIT("events")}, events_status_init, events_status_per_thread, events_status_final,
-};
diff --git a/web/server/h2o/libh2o/lib/handler/status/requests.c b/web/server/h2o/libh2o/lib/handler/status/requests.c
deleted file mode 100644
index 4854e4a1f..000000000
--- a/web/server/h2o/libh2o/lib/handler/status/requests.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 "h2o.h"
-
-struct st_requests_status_ctx_t {
- h2o_logconf_t *logconf;
- h2o_iovec_t req_data;
- pthread_mutex_t mutex;
-};
-
-struct st_collect_req_status_cbdata_t {
- h2o_logconf_t *logconf;
- h2o_buffer_t *buffer;
-};
-
-static int collect_req_status(h2o_req_t *req, void *_cbdata)
-{
- struct st_collect_req_status_cbdata_t *cbdata = _cbdata;
-
- /* collect log */
- char buf[4096];
- size_t len = sizeof(buf);
- char *logline = h2o_log_request(cbdata->logconf, req, &len, buf);
- assert(len != 0);
- --len; /* omit trailing LF */
-
- /* append to buffer */
- h2o_buffer_reserve(&cbdata->buffer, len + 3);
- memcpy(cbdata->buffer->bytes + cbdata->buffer->size, logline, len);
- cbdata->buffer->size += len;
-
- if (logline != buf)
- free(logline);
-
- return 0;
-}
-
-static void requests_status_per_thread(void *priv, h2o_context_t *ctx)
-{
- struct st_requests_status_ctx_t *rsc = priv;
- struct st_collect_req_status_cbdata_t cbdata = {rsc->logconf};
-
- /* we encountered an error at init() time, return early */
- if (rsc->logconf == NULL)
- return;
-
- h2o_buffer_init(&cbdata.buffer, &h2o_socket_buffer_prototype);
- ctx->globalconf->http1.callbacks.foreach_request(ctx, collect_req_status, &cbdata);
- ctx->globalconf->http2.callbacks.foreach_request(ctx, collect_req_status, &cbdata);
-
- /* concat JSON elements */
- if (cbdata.buffer->size != 0) {
- pthread_mutex_lock(&rsc->mutex);
- if (rsc->req_data.len == 0)
- h2o_buffer_consume(&cbdata.buffer, 1); /* skip preceeding comma */
- rsc->req_data.base = h2o_mem_realloc(rsc->req_data.base, rsc->req_data.len + cbdata.buffer->size);
- memcpy(rsc->req_data.base + rsc->req_data.len, cbdata.buffer->bytes, cbdata.buffer->size);
- rsc->req_data.len += cbdata.buffer->size;
- pthread_mutex_unlock(&rsc->mutex);
- }
-
- h2o_buffer_dispose(&cbdata.buffer);
-}
-
-static void *requests_status_init(void)
-{
- struct st_requests_status_ctx_t *rsc = h2o_mem_alloc(sizeof(*rsc));
- char errbuf[256];
-
-#define ELEMENT(key, expr) "\"" key "\": \"" expr "\""
-#define X_ELEMENT(id) ELEMENT(id, "%{" id "}x")
-#define SEPARATOR ", "
- const char *fmt = ",\n {"
- /* combined_log */
- ELEMENT("host", "%h") SEPARATOR ELEMENT("user", "%u") SEPARATOR ELEMENT("at", "%{%Y%m%dT%H%M%S}t.%{usec_frac}t%{%z}t")
- SEPARATOR ELEMENT("method", "%m") SEPARATOR ELEMENT("path", "%U") SEPARATOR ELEMENT("query", "%q")
- SEPARATOR ELEMENT("protocol", "%H") SEPARATOR ELEMENT("referer", "%{Referer}i")
- SEPARATOR ELEMENT("user-agent", "%{User-agent}i") SEPARATOR
- /* time */
- X_ELEMENT("connect-time") SEPARATOR X_ELEMENT("request-header-time") SEPARATOR X_ELEMENT("request-body-time")
- SEPARATOR X_ELEMENT("request-total-time") SEPARATOR X_ELEMENT("process-time") SEPARATOR X_ELEMENT("response-time")
- SEPARATOR
- /* connection */
- X_ELEMENT("connection-id") SEPARATOR X_ELEMENT("ssl.protocol-version") SEPARATOR X_ELEMENT("ssl.session-reused")
- SEPARATOR X_ELEMENT("ssl.cipher") SEPARATOR X_ELEMENT("ssl.cipher-bits") SEPARATOR X_ELEMENT("ssl.session-ticket")
- SEPARATOR
- /* http1 */
- X_ELEMENT("http1.request-index") SEPARATOR
- /* http2 */
- X_ELEMENT("http2.stream-id") SEPARATOR X_ELEMENT("http2.priority.received.exclusive")
- SEPARATOR X_ELEMENT("http2.priority.received.parent") SEPARATOR X_ELEMENT("http2.priority.received.weight")
- SEPARATOR X_ELEMENT("http2.priority.actual.parent") SEPARATOR X_ELEMENT("http2.priority.actual.weight") SEPARATOR
- /* misc */
- ELEMENT("authority", "%V")
- /* end */
- "}";
-#undef ELEMENT
-#undef X_ELEMENT
-#undef SEPARATOR
-
- /* compile logconf */
- if ((rsc->logconf = h2o_logconf_compile(fmt, H2O_LOGCONF_ESCAPE_JSON, errbuf)) == NULL)
- /* log format compilation error is an internal logic flaw, therefore we need not send the details to the client */
- fprintf(stderr, "[lib/handler/status/requests.c] failed to compile log format: %s", errbuf);
-
- rsc->req_data = (h2o_iovec_t){NULL};
- pthread_mutex_init(&rsc->mutex, NULL);
-
- return rsc;
-}
-
-static h2o_iovec_t requests_status_final(void *priv, h2o_globalconf_t *gconf, h2o_req_t *req)
-{
- h2o_iovec_t ret = {NULL};
- struct st_requests_status_ctx_t *rsc = priv;
-
- if (rsc->logconf != NULL) {
- ret = h2o_concat(&req->pool, h2o_iovec_init(H2O_STRLIT(",\n \"requests\": [")), rsc->req_data,
- h2o_iovec_init(H2O_STRLIT("\n ]")));
- h2o_logconf_dispose(rsc->logconf);
- }
- free(rsc->req_data.base);
- pthread_mutex_destroy(&rsc->mutex);
-
- free(rsc);
- return ret;
-}
-
-h2o_status_handler_t requests_status_handler = {
- {H2O_STRLIT("requests")}, requests_status_init, requests_status_per_thread, requests_status_final,
-};
diff --git a/web/server/h2o/libh2o/lib/handler/throttle_resp.c b/web/server/h2o/libh2o/lib/handler/throttle_resp.c
deleted file mode 100644
index a0028b502..000000000
--- a/web/server/h2o/libh2o/lib/handler/throttle_resp.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2016 Justin Zhu
- *
- * 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 <stdlib.h>
-#include "h2o.h"
-
-#ifndef HUNDRED_MS
-#define HUNDRED_MS 100
-#endif
-
-#ifndef ONE_SECOND
-#define ONE_SECOND 1000
-#endif
-
-typedef H2O_VECTOR(h2o_iovec_t) iovec_vector_t;
-
-typedef struct st_throttle_resp_t {
- h2o_ostream_t super;
- h2o_timeout_entry_t timeout_entry;
- int64_t tokens;
- size_t token_inc;
- h2o_context_t *ctx;
- h2o_req_t *req;
- struct {
- iovec_vector_t bufs;
- h2o_send_state_t stream_state;
- } state;
-} throttle_resp_t;
-
-static void real_send(throttle_resp_t *self)
-{
- /* a really simple token bucket implementation */
- assert(self->tokens > 0);
- size_t i, token_consume;
-
- token_consume = 0;
-
- for (i = 0; i < self->state.bufs.size; i++) {
- token_consume += self->state.bufs.entries[i].len;
- }
-
- self->tokens -= token_consume;
-
- h2o_ostream_send_next(&self->super, self->req, self->state.bufs.entries, self->state.bufs.size, self->state.stream_state);
- if (!h2o_send_state_is_in_progress(self->state.stream_state))
- h2o_timeout_unlink(&self->timeout_entry);
-}
-
-static void add_token(h2o_timeout_entry_t *entry)
-{
- throttle_resp_t *self = H2O_STRUCT_FROM_MEMBER(throttle_resp_t, timeout_entry, entry);
-
- h2o_timeout_link(self->ctx->loop, &self->ctx->hundred_ms_timeout, &self->timeout_entry);
- self->tokens += self->token_inc;
-
- if (self->tokens > 0)
- real_send(self);
-}
-
-static void on_send(h2o_ostream_t *_self, h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state)
-{
- throttle_resp_t *self = (void *)_self;
- size_t i;
-
- /* I don't know if this is a proper way. */
- h2o_vector_reserve(&req->pool, &self->state.bufs, inbufcnt);
- /* start to save state */
- for (i = 0; i < inbufcnt; ++i) {
- self->state.bufs.entries[i] = inbufs[i];
- }
- self->state.bufs.size = inbufcnt;
- self->state.stream_state = state;
-
- /* if there's token, we try to send */
- if (self->tokens > 0)
- real_send(self);
-}
-
-static void on_stop(h2o_ostream_t *_self, h2o_req_t *req)
-{
- throttle_resp_t *self = (void *)_self;
- if (h2o_timeout_is_linked(&self->timeout_entry)) {
- h2o_timeout_unlink(&self->timeout_entry);
- }
-}
-
-static void on_setup_ostream(h2o_filter_t *self, h2o_req_t *req, h2o_ostream_t **slot)
-{
- throttle_resp_t *throttle;
- h2o_iovec_t traffic_header_value;
- size_t traffic_limit;
-
- if (req->res.status != 200)
- goto Next;
- if (h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("HEAD")))
- goto Next;
-
- ssize_t xt_index;
- if ((xt_index = h2o_find_header(&req->res.headers, H2O_TOKEN_X_TRAFFIC, -1)) == -1)
- goto Next;
-
- traffic_header_value = req->res.headers.entries[xt_index].value;
- char *buf = traffic_header_value.base;
-
- if (H2O_UNLIKELY((traffic_limit = h2o_strtosizefwd(&buf, traffic_header_value.len)) == SIZE_MAX))
- goto Next;
-
- throttle = (void *)h2o_add_ostream(req, sizeof(throttle_resp_t), slot);
-
- /* calculate the token increment per 100ms */
- throttle->token_inc = traffic_limit * HUNDRED_MS / ONE_SECOND;
- if (req->preferred_chunk_size > throttle->token_inc)
- req->preferred_chunk_size = throttle->token_inc;
-
- h2o_delete_header(&req->res.headers, xt_index);
-
- throttle->super.do_send = on_send;
- throttle->super.stop = on_stop;
- throttle->ctx = req->conn->ctx;
- throttle->req = req;
- throttle->state.bufs.capacity = 0;
- throttle->state.bufs.size = 0;
- throttle->timeout_entry = (h2o_timeout_entry_t){0};
- throttle->timeout_entry.cb = add_token;
- throttle->tokens = throttle->token_inc;
- slot = &throttle->super.next;
-
- h2o_timeout_link(throttle->ctx->loop, &throttle->ctx->hundred_ms_timeout, &throttle->timeout_entry);
-
-Next:
- h2o_setup_next_ostream(req, slot);
-}
-
-void h2o_throttle_resp_register(h2o_pathconf_t *pathconf)
-{
- h2o_filter_t *self = h2o_create_filter(pathconf, sizeof(*self));
- self->on_setup_ostream = on_setup_ostream;
-}
diff --git a/web/server/h2o/libh2o/lib/http1.c b/web/server/h2o/libh2o/lib/http1.c
deleted file mode 100644
index 98c4e55ab..000000000
--- a/web/server/h2o/libh2o/lib/http1.c
+++ /dev/null
@@ -1,859 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Shota Fukumori,
- * Fastly, Inc.
- *
- * 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 <inttypes.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "picohttpparser.h"
-#include "h2o.h"
-#include "h2o/http1.h"
-#include "h2o/http2.h"
-
-#define MAX_PULL_BUF_SZ 65536
-
-struct st_h2o_http1_finalostream_t {
- h2o_ostream_t super;
- int sent_headers;
- struct {
- void *buf;
- h2o_ostream_pull_cb cb;
- } pull;
-};
-
-struct st_h2o_http1_conn_t {
- h2o_conn_t super;
- h2o_socket_t *sock;
- /* internal structure */
- h2o_linklist_t _conns;
- h2o_timeout_t *_timeout;
- h2o_timeout_entry_t _timeout_entry;
- uint64_t _req_index;
- size_t _prevreqlen;
- size_t _reqsize;
- struct st_h2o_http1_req_entity_reader *_req_entity_reader;
- struct st_h2o_http1_finalostream_t _ostr_final;
- struct {
- void *data;
- h2o_http1_upgrade_cb cb;
- } upgrade;
- /* the HTTP request / response (intentionally placed at the last, since it is a large structure and has it's own ctor) */
- h2o_req_t req;
-};
-
-struct st_h2o_http1_req_entity_reader {
- void (*handle_incoming_entity)(struct st_h2o_http1_conn_t *conn);
-};
-
-struct st_h2o_http1_content_length_entity_reader {
- struct st_h2o_http1_req_entity_reader super;
- size_t content_length;
-};
-
-struct st_h2o_http1_chunked_entity_reader {
- struct st_h2o_http1_req_entity_reader super;
- struct phr_chunked_decoder decoder;
- size_t prev_input_size;
-};
-
-static void proceed_pull(struct st_h2o_http1_conn_t *conn, size_t nfilled);
-static void finalostream_start_pull(h2o_ostream_t *_self, h2o_ostream_pull_cb cb);
-static void finalostream_send(h2o_ostream_t *_self, h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t state);
-static void reqread_on_read(h2o_socket_t *sock, const char *err);
-static int foreach_request(h2o_context_t *ctx, int (*cb)(h2o_req_t *req, void *cbdata), void *cbdata);
-
-const h2o_protocol_callbacks_t H2O_HTTP1_CALLBACKS = {
- NULL, /* graceful_shutdown (note: nothing special needs to be done for handling graceful shutdown) */
- foreach_request};
-
-static int is_msie(h2o_req_t *req)
-{
- ssize_t cursor = h2o_find_header(&req->headers, H2O_TOKEN_USER_AGENT, -1);
- if (cursor == -1)
- return 0;
- if (h2o_strstr(req->headers.entries[cursor].value.base, req->headers.entries[cursor].value.len, H2O_STRLIT("; MSIE ")) ==
- SIZE_MAX)
- return 0;
- return 1;
-}
-
-static void init_request(struct st_h2o_http1_conn_t *conn, int reinit)
-{
- if (reinit)
- h2o_dispose_request(&conn->req);
- h2o_init_request(&conn->req, &conn->super, NULL);
-
- ++conn->_req_index;
- conn->req._ostr_top = &conn->_ostr_final.super;
- conn->_ostr_final.super.do_send = finalostream_send;
- conn->_ostr_final.super.start_pull = finalostream_start_pull;
- conn->_ostr_final.sent_headers = 0;
-}
-
-static void close_connection(struct st_h2o_http1_conn_t *conn, int close_socket)
-{
- h2o_timeout_unlink(&conn->_timeout_entry);
- h2o_dispose_request(&conn->req);
- if (conn->sock != NULL && close_socket)
- h2o_socket_close(conn->sock);
- h2o_linklist_unlink(&conn->_conns);
- free(conn);
-}
-
-static void set_timeout(struct st_h2o_http1_conn_t *conn, h2o_timeout_t *timeout, h2o_timeout_cb cb)
-{
- if (conn->_timeout != NULL) {
- h2o_timeout_unlink(&conn->_timeout_entry);
- conn->_timeout_entry.cb = NULL;
- }
- conn->_timeout = timeout;
- if (timeout != NULL) {
- h2o_timeout_link(conn->super.ctx->loop, timeout, &conn->_timeout_entry);
- conn->_timeout_entry.cb = cb;
- }
-}
-
-static void process_request(struct st_h2o_http1_conn_t *conn)
-{
- if (conn->sock->ssl == NULL && conn->req.upgrade.base != NULL && conn->super.ctx->globalconf->http1.upgrade_to_http2 &&
- conn->req.upgrade.len >= 3 && h2o_lcstris(conn->req.upgrade.base, 3, H2O_STRLIT("h2c")) &&
- (conn->req.upgrade.len == 3 ||
- (conn->req.upgrade.len == 6 && (memcmp(conn->req.upgrade.base + 3, H2O_STRLIT("-14")) == 0 ||
- memcmp(conn->req.upgrade.base + 3, H2O_STRLIT("-16")) == 0)))) {
- if (h2o_http2_handle_upgrade(&conn->req, conn->super.connected_at) == 0) {
- return;
- }
- }
- h2o_process_request(&conn->req);
-}
-
-#define DECL_ENTITY_READ_SEND_ERROR_XXX(status_) \
- static void entity_read_send_error_##status_(struct st_h2o_http1_conn_t *conn, const char *reason, const char *body) \
- { \
- conn->_req_entity_reader = NULL; \
- set_timeout(conn, NULL, NULL); \
- h2o_socket_read_stop(conn->sock); \
- conn->req.http1_is_persistent = 0; \
- conn->super.ctx->emitted_error_status[H2O_STATUS_ERROR_##status_]++; \
- h2o_send_error_generic(&conn->req, status_, reason, body, H2O_SEND_ERROR_HTTP1_CLOSE_CONNECTION); \
- }
-
-DECL_ENTITY_READ_SEND_ERROR_XXX(400)
-DECL_ENTITY_READ_SEND_ERROR_XXX(413)
-
-static void on_entity_read_complete(struct st_h2o_http1_conn_t *conn)
-{
- conn->_req_entity_reader = NULL;
- set_timeout(conn, NULL, NULL);
- h2o_socket_read_stop(conn->sock);
- process_request(conn);
-}
-
-static void handle_chunked_entity_read(struct st_h2o_http1_conn_t *conn)
-{
- struct st_h2o_http1_chunked_entity_reader *reader = (void *)conn->_req_entity_reader;
- h2o_buffer_t *inbuf = conn->sock->input;
- size_t bufsz;
- ssize_t ret;
-
- /* decode the incoming data */
- if ((bufsz = inbuf->size - reader->prev_input_size) == 0)
- return;
- ret = phr_decode_chunked(&reader->decoder, inbuf->bytes + reader->prev_input_size, &bufsz);
- inbuf->size = reader->prev_input_size + bufsz;
- reader->prev_input_size = inbuf->size;
- if (ret != -1 && inbuf->size - conn->_reqsize >= conn->super.ctx->globalconf->max_request_entity_size) {
- entity_read_send_error_413(conn, "Request Entity Too Large", "request entity is too large");
- return;
- }
- if (ret < 0) {
- if (ret == -2) {
- /* incomplete */
- return;
- }
- /* error */
- entity_read_send_error_400(conn, "Invalid Request", "broken chunked-encoding");
- return;
- }
- /* complete */
- conn->req.entity = h2o_iovec_init(inbuf->bytes + conn->_reqsize, inbuf->size - conn->_reqsize);
- conn->_reqsize = inbuf->size;
- inbuf->size += ret; /* restore the number of extra bytes */
-
- on_entity_read_complete(conn);
-}
-
-static int create_chunked_entity_reader(struct st_h2o_http1_conn_t *conn)
-{
- struct st_h2o_http1_chunked_entity_reader *reader = h2o_mem_alloc_pool(&conn->req.pool, sizeof(*reader));
- conn->_req_entity_reader = &reader->super;
-
- reader->super.handle_incoming_entity = handle_chunked_entity_read;
- memset(&reader->decoder, 0, sizeof(reader->decoder));
- reader->decoder.consume_trailer = 1;
- reader->prev_input_size = conn->_reqsize;
-
- return 0;
-}
-
-static void handle_content_length_entity_read(struct st_h2o_http1_conn_t *conn)
-{
- struct st_h2o_http1_content_length_entity_reader *reader = (void *)conn->_req_entity_reader;
-
- /* wait until: reqsize == conn->_input.size */
- if (conn->sock->input->size < conn->_reqsize)
- return;
-
- /* all input has arrived */
- conn->req.entity = h2o_iovec_init(conn->sock->input->bytes + conn->_reqsize - reader->content_length, reader->content_length);
- on_entity_read_complete(conn);
-}
-
-static int create_content_length_entity_reader(struct st_h2o_http1_conn_t *conn, size_t content_length)
-{
- struct st_h2o_http1_content_length_entity_reader *reader = h2o_mem_alloc_pool(&conn->req.pool, sizeof(*reader));
- conn->_req_entity_reader = &reader->super;
-
- reader->super.handle_incoming_entity = handle_content_length_entity_read;
- reader->content_length = content_length;
- conn->_reqsize += content_length;
-
- return 0;
-}
-
-static int create_entity_reader(struct st_h2o_http1_conn_t *conn, const struct phr_header *entity_header)
-{
- /* strlen("content-length") is unequal to sizeof("transfer-encoding"), and thus checking the length only is sufficient */
- if (entity_header->name_len == sizeof("transfer-encoding") - 1) {
- /* transfer-encoding */
- if (!h2o_lcstris(entity_header->value, entity_header->value_len, H2O_STRLIT("chunked"))) {
- entity_read_send_error_400(conn, "Invalid Request", "unknown transfer-encoding");
- return -1;
- }
- return create_chunked_entity_reader(conn);
- } else {
- /* content-length */
- size_t content_length = h2o_strtosize(entity_header->value, entity_header->value_len);
- if (content_length == SIZE_MAX) {
- entity_read_send_error_400(conn, "Invalid Request", "broken content-length header");
- return -1;
- }
- if (content_length > conn->super.ctx->globalconf->max_request_entity_size) {
- entity_read_send_error_413(conn, "Request Entity Too Large", "request entity is too large");
- return -1;
- }
- return create_content_length_entity_reader(conn, (size_t)content_length);
- }
- /* failed */
- return -1;
-}
-
-static ssize_t init_headers(h2o_mem_pool_t *pool, h2o_headers_t *headers, const struct phr_header *src, size_t len,
- h2o_iovec_t *connection, h2o_iovec_t *host, h2o_iovec_t *upgrade, h2o_iovec_t *expect)
-{
- ssize_t entity_header_index = -1;
-
- assert(headers->size == 0);
-
- /* setup */
- if (len != 0) {
- size_t i;
- h2o_vector_reserve(pool, headers, len);
- for (i = 0; i != len; ++i) {
- const h2o_token_t *name_token;
- char orig_case[src[i].name_len];
-
- /* preserve the original case */
- memcpy(orig_case, src[i].name, src[i].name_len);
- /* convert to lower-case in-place */
- h2o_strtolower((char *)src[i].name, src[i].name_len);
- if ((name_token = h2o_lookup_token(src[i].name, src[i].name_len)) != NULL) {
- if (name_token->is_init_header_special) {
- if (name_token == H2O_TOKEN_HOST) {
- host->base = (char *)src[i].value;
- host->len = src[i].value_len;
- } else if (name_token == H2O_TOKEN_CONTENT_LENGTH) {
- if (entity_header_index == -1)
- entity_header_index = i;
- } else if (name_token == H2O_TOKEN_TRANSFER_ENCODING) {
- entity_header_index = i;
- } else if (name_token == H2O_TOKEN_EXPECT) {
- expect->base = (char *)src[i].value;
- expect->len = src[i].value_len;
- } else if (name_token == H2O_TOKEN_UPGRADE) {
- upgrade->base = (char *)src[i].value;
- upgrade->len = src[i].value_len;
- } else {
- assert(!"logic flaw");
- }
- } else {
- h2o_add_header(pool, headers, name_token, orig_case, src[i].value, src[i].value_len);
- if (name_token == H2O_TOKEN_CONNECTION)
- *connection = headers->entries[headers->size - 1].value;
- }
- } else {
- h2o_add_header_by_str(pool, headers, src[i].name, src[i].name_len, 0, orig_case, src[i].value, src[i].value_len);
- }
- }
- }
-
- return entity_header_index;
-}
-
-static ssize_t fixup_request(struct st_h2o_http1_conn_t *conn, struct phr_header *headers, size_t num_headers, int minor_version,
- h2o_iovec_t *expect)
-{
- ssize_t entity_header_index;
- h2o_iovec_t connection = {NULL, 0}, host = {NULL, 0}, upgrade = {NULL, 0};
-
- expect->base = NULL;
- expect->len = 0;
-
- conn->req.input.scheme = conn->sock->ssl != NULL ? &H2O_URL_SCHEME_HTTPS : &H2O_URL_SCHEME_HTTP;
- conn->req.version = 0x100 | (minor_version != 0);
-
- /* init headers */
- entity_header_index =
- init_headers(&conn->req.pool, &conn->req.headers, headers, num_headers, &connection, &host, &upgrade, expect);
-
- /* copy the values to pool, since the buffer pointed by the headers may get realloced */
- if (entity_header_index != -1) {
- size_t i;
- conn->req.input.method = h2o_strdup(&conn->req.pool, conn->req.input.method.base, conn->req.input.method.len);
- conn->req.input.path = h2o_strdup(&conn->req.pool, conn->req.input.path.base, conn->req.input.path.len);
- for (i = 0; i != conn->req.headers.size; ++i) {
- h2o_header_t *header = conn->req.headers.entries + i;
- if (!h2o_iovec_is_token(header->name)) {
- *header->name = h2o_strdup(&conn->req.pool, header->name->base, header->name->len);
- }
- header->value = h2o_strdup(&conn->req.pool, header->value.base, header->value.len);
- }
- if (host.base != NULL)
- host = h2o_strdup(&conn->req.pool, host.base, host.len);
- if (upgrade.base != NULL)
- upgrade = h2o_strdup(&conn->req.pool, upgrade.base, upgrade.len);
- }
-
- /* move host header to req->authority */
- if (host.base != NULL)
- conn->req.input.authority = host;
-
- /* setup persistent flag (and upgrade info) */
- if (connection.base != NULL) {
- /* TODO contains_token function can be faster */
- if (h2o_contains_token(connection.base, connection.len, H2O_STRLIT("keep-alive"), ',')) {
- conn->req.http1_is_persistent = 1;
- }
- if (upgrade.base != NULL && h2o_contains_token(connection.base, connection.len, H2O_STRLIT("upgrade"), ',')) {
- conn->req.upgrade = upgrade;
- }
- } else if (conn->req.version >= 0x101) {
- /* defaults to keep-alive if >= HTTP/1.1 */
- conn->req.http1_is_persistent = 1;
- }
- /* disable keep-alive if shutdown is requested */
- if (conn->req.http1_is_persistent && conn->super.ctx->shutdown_requested)
- conn->req.http1_is_persistent = 0;
-
- return entity_header_index;
-}
-
-static void on_continue_sent(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1_conn_t *conn = sock->data;
-
- if (err != NULL) {
- close_connection(conn, 1);
- return;
- }
-
- h2o_socket_read_start(sock, reqread_on_read);
- conn->_req_entity_reader->handle_incoming_entity(conn);
-}
-
-static int contains_crlf_only(const char *s, size_t len)
-{
- for (; len != 0; ++s, --len)
- if (!(*s == '\r' || *s == '\n'))
- return 0;
- return 1;
-}
-
-static void send_bad_request_on_complete(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1_conn_t *conn = sock->data;
- close_connection(conn, 1);
-}
-
-static void send_bad_request(struct st_h2o_http1_conn_t *conn)
-{
- const static h2o_iovec_t resp = {H2O_STRLIT("HTTP/1.1 400 Bad Request\r\n"
- "Content-Type: text/plain; charset=utf-8\r\n"
- "Connection: close\r\n"
- "Content-Length: 11\r\n"
- "\r\n"
- "Bad Request")};
-
- assert(conn->req.version == 0 && "request has not been parsed successfully");
- assert(conn->req.http1_is_persistent == 0);
- h2o_socket_write(conn->sock, (h2o_iovec_t *)&resp, 1, send_bad_request_on_complete);
- h2o_socket_read_stop(conn->sock);
-}
-
-static void handle_incoming_request(struct st_h2o_http1_conn_t *conn)
-{
- size_t inreqlen = conn->sock->input->size < H2O_MAX_REQLEN ? conn->sock->input->size : H2O_MAX_REQLEN;
- int reqlen, minor_version;
- struct phr_header headers[H2O_MAX_HEADERS];
- size_t num_headers = H2O_MAX_HEADERS;
- ssize_t entity_body_header_index;
- h2o_iovec_t expect;
-
- /* need to set request_begin_at here for keep-alive connection */
- if (conn->req.timestamps.request_begin_at.tv_sec == 0)
- conn->req.timestamps.request_begin_at = *h2o_get_timestamp(conn->super.ctx, NULL, NULL);
-
- reqlen = phr_parse_request(conn->sock->input->bytes, inreqlen, (const char **)&conn->req.input.method.base,
- &conn->req.input.method.len, (const char **)&conn->req.input.path.base, &conn->req.input.path.len,
- &minor_version, headers, &num_headers, conn->_prevreqlen);
- conn->_prevreqlen = inreqlen;
-
- switch (reqlen) {
- default: // parse complete
- conn->_reqsize = reqlen;
- if ((entity_body_header_index = fixup_request(conn, headers, num_headers, minor_version, &expect)) != -1) {
- conn->req.timestamps.request_body_begin_at = *h2o_get_timestamp(conn->super.ctx, NULL, NULL);
- if (expect.base != NULL) {
- if (!h2o_lcstris(expect.base, expect.len, H2O_STRLIT("100-continue"))) {
- set_timeout(conn, NULL, NULL);
- h2o_socket_read_stop(conn->sock);
- h2o_send_error_417(&conn->req, "Expectation Failed", "unknown expectation",
- H2O_SEND_ERROR_HTTP1_CLOSE_CONNECTION);
- return;
- }
- }
- if (create_entity_reader(conn, headers + entity_body_header_index) != 0) {
- return;
- }
- if (expect.base != NULL) {
- static const h2o_iovec_t res = {H2O_STRLIT("HTTP/1.1 100 Continue\r\n\r\n")};
- h2o_socket_write(conn->sock, (void *)&res, 1, on_continue_sent);
- /* processing of the incoming entity is postponed until the 100 response is sent */
- h2o_socket_read_stop(conn->sock);
- return;
- }
- conn->_req_entity_reader->handle_incoming_entity(conn);
- } else {
- set_timeout(conn, NULL, NULL);
- h2o_socket_read_stop(conn->sock);
- process_request(conn);
- }
- return;
- case -2: // incomplete
- if (inreqlen == H2O_MAX_REQLEN) {
- send_bad_request(conn);
- }
- return;
- case -1: // error
- /* upgrade to HTTP/2 if the request starts with: PRI * HTTP/2 */
- if (conn->super.ctx->globalconf->http1.upgrade_to_http2) {
- /* should check up to the first octet that phr_parse_request returns an error */
- static const h2o_iovec_t HTTP2_SIG = {H2O_STRLIT("PRI * HTTP/2")};
- if (conn->sock->input->size >= HTTP2_SIG.len && memcmp(conn->sock->input->bytes, HTTP2_SIG.base, HTTP2_SIG.len) == 0) {
- h2o_accept_ctx_t accept_ctx = {conn->super.ctx, conn->super.hosts};
- h2o_socket_t *sock = conn->sock;
- struct timeval connected_at = conn->super.connected_at;
- /* destruct the connection after detatching the socket */
- conn->sock = NULL;
- close_connection(conn, 1);
- /* and accept as http2 connection */
- h2o_http2_accept(&accept_ctx, sock, connected_at);
- return;
- }
- }
- if (inreqlen <= 4 && contains_crlf_only(conn->sock->input->bytes, inreqlen)) {
- close_connection(conn, 1);
- } else {
- send_bad_request(conn);
- }
- return;
- }
-}
-
-void reqread_on_read(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1_conn_t *conn = sock->data;
-
- if (err != NULL) {
- close_connection(conn, 1);
- return;
- }
-
- if (conn->_req_entity_reader == NULL)
- handle_incoming_request(conn);
- else
- conn->_req_entity_reader->handle_incoming_entity(conn);
-}
-
-static void reqread_on_timeout(h2o_timeout_entry_t *entry)
-{
- struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, _timeout_entry, entry);
-
- /* TODO log */
- conn->req.http1_is_persistent = 0;
- close_connection(conn, 1);
-}
-
-static inline void reqread_start(struct st_h2o_http1_conn_t *conn)
-{
- set_timeout(conn, &conn->super.ctx->http1.req_timeout, reqread_on_timeout);
- h2o_socket_read_start(conn->sock, reqread_on_read);
- if (conn->sock->input->size != 0)
- handle_incoming_request(conn);
-}
-
-static void on_send_next_push(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1_conn_t *conn = sock->data;
-
- if (err != NULL)
- close_connection(conn, 1);
- else
- h2o_proceed_response(&conn->req);
-}
-
-static void on_send_next_pull(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1_conn_t *conn = sock->data;
-
- if (err != NULL)
- close_connection(conn, 1);
- else
- proceed_pull(conn, 0);
-}
-
-static void on_send_complete(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_http1_conn_t *conn = sock->data;
-
- assert(conn->req._ostr_top == &conn->_ostr_final.super);
-
- conn->req.timestamps.response_end_at = *h2o_get_timestamp(conn->super.ctx, NULL, NULL);
-
- if (!conn->req.http1_is_persistent) {
- /* TODO use lingering close */
- close_connection(conn, 1);
- return;
- }
-
- /* handle next request */
- init_request(conn, 1);
- h2o_buffer_consume(&conn->sock->input, conn->_reqsize);
- conn->_prevreqlen = 0;
- conn->_reqsize = 0;
- reqread_start(conn);
-}
-
-static void on_upgrade_complete(h2o_socket_t *socket, const char *err)
-{
- struct st_h2o_http1_conn_t *conn = socket->data;
- h2o_http1_upgrade_cb cb = conn->upgrade.cb;
- void *data = conn->upgrade.data;
- h2o_socket_t *sock = NULL;
- size_t reqsize = 0;
-
- /* destruct the connection (after detaching the socket) */
- if (err == 0) {
- sock = conn->sock;
- reqsize = conn->_reqsize;
- close_connection(conn, 0);
- } else {
- close_connection(conn, 1);
- }
-
- cb(data, sock, reqsize);
-}
-
-static size_t flatten_headers_estimate_size(h2o_req_t *req, size_t server_name_and_connection_len)
-{
- size_t len = sizeof("HTTP/1.1 \r\ndate: \r\nserver: \r\nconnection: \r\ncontent-length: \r\n\r\n") + 3 +
- strlen(req->res.reason) + H2O_TIMESTR_RFC1123_LEN + server_name_and_connection_len +
- sizeof(H2O_UINT64_LONGEST_STR) - 1 + sizeof("cache-control: private") - 1;
- const h2o_header_t *header, *end;
-
- for (header = req->res.headers.entries, end = header + req->res.headers.size; header != end; ++header)
- len += header->name->len + header->value.len + 4;
-
- return len;
-}
-
-static size_t flatten_headers(char *buf, h2o_req_t *req, const char *connection)
-{
- h2o_context_t *ctx = req->conn->ctx;
- h2o_timestamp_t ts;
- char *dst = buf;
-
- h2o_get_timestamp(ctx, &req->pool, &ts);
-
- assert(req->res.status <= 999);
-
- /* send essential headers with the first chars uppercased for max. interoperability (#72) */
- if (req->res.content_length != SIZE_MAX) {
- dst += sprintf(dst, "HTTP/1.1 %d %s\r\nDate: %s\r\nConnection: %s\r\nContent-Length: %zu\r\n", req->res.status,
- req->res.reason, ts.str->rfc1123, connection, req->res.content_length);
- } else {
- dst += sprintf(dst, "HTTP/1.1 %d %s\r\nDate: %s\r\nConnection: %s\r\n", req->res.status, req->res.reason, ts.str->rfc1123,
- connection);
- }
- if (ctx->globalconf->server_name.len) {
- dst += sprintf(dst, "Server: %s\r\n", ctx->globalconf->server_name.base);
- }
-
- { /* flatten the normal headers */
- size_t i;
- for (i = 0; i != req->res.headers.size; ++i) {
- const h2o_header_t *header = req->res.headers.entries + i;
- if (header->name == &H2O_TOKEN_VARY->buf) {
- /* replace Vary with Cache-Control: private; see the following URLs to understand why this is necessary
- * - http://blogs.msdn.com/b/ieinternals/archive/2009/06/17/vary-header-prevents-caching-in-ie.aspx
- * - https://www.igvita.com/2013/05/01/deploying-webp-via-accept-content-negotiation/
- */
- if (is_msie(req)) {
- static h2o_header_t cache_control_private = {&H2O_TOKEN_CACHE_CONTROL->buf, NULL, {H2O_STRLIT("private")}};
- header = &cache_control_private;
- }
- }
- memcpy(dst, header->orig_name ? header->orig_name : header->name->base, header->name->len);
- dst += header->name->len;
- *dst++ = ':';
- *dst++ = ' ';
- memcpy(dst, header->value.base, header->value.len);
- dst += header->value.len;
- *dst++ = '\r';
- *dst++ = '\n';
- }
- *dst++ = '\r';
- *dst++ = '\n';
- }
-
- return dst - buf;
-}
-
-static void proceed_pull(struct st_h2o_http1_conn_t *conn, size_t nfilled)
-{
- h2o_iovec_t buf = {conn->_ostr_final.pull.buf, nfilled};
- h2o_send_state_t send_state;
-
- if (buf.len < MAX_PULL_BUF_SZ) {
- h2o_iovec_t cbuf = {buf.base + buf.len, MAX_PULL_BUF_SZ - buf.len};
- send_state = h2o_pull(&conn->req, conn->_ostr_final.pull.cb, &cbuf);
- if (send_state == H2O_SEND_STATE_ERROR) {
- conn->req.http1_is_persistent = 0;
- }
- buf.len += cbuf.len;
- conn->req.bytes_sent += cbuf.len;
- } else {
- send_state = H2O_SEND_STATE_IN_PROGRESS;
- }
-
- /* write */
- h2o_socket_write(conn->sock, &buf, 1, h2o_send_state_is_in_progress(send_state) ? on_send_next_pull : on_send_complete);
-}
-
-static void finalostream_start_pull(h2o_ostream_t *_self, h2o_ostream_pull_cb cb)
-{
- struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, _ostr_final.super, _self);
- const char *connection = conn->req.http1_is_persistent ? "keep-alive" : "close";
- size_t bufsz, headers_len;
-
- assert(conn->req._ostr_top == &conn->_ostr_final.super);
- assert(!conn->_ostr_final.sent_headers);
-
- conn->req.timestamps.response_start_at = *h2o_get_timestamp(conn->super.ctx, NULL, NULL);
-
- /* register the pull callback */
- conn->_ostr_final.pull.cb = cb;
-
- /* setup the buffer */
- bufsz = flatten_headers_estimate_size(&conn->req, conn->super.ctx->globalconf->server_name.len + strlen(connection));
- if (bufsz < MAX_PULL_BUF_SZ) {
- if (MAX_PULL_BUF_SZ - bufsz < conn->req.res.content_length) {
- bufsz = MAX_PULL_BUF_SZ;
- } else {
- bufsz += conn->req.res.content_length;
- }
- }
- conn->_ostr_final.pull.buf = h2o_mem_alloc_pool(&conn->req.pool, bufsz);
-
- /* fill-in the header */
- headers_len = flatten_headers(conn->_ostr_final.pull.buf, &conn->req, connection);
- conn->_ostr_final.sent_headers = 1;
-
- proceed_pull(conn, headers_len);
-}
-
-void finalostream_send(h2o_ostream_t *_self, h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_send_state_t send_state)
-{
- struct st_h2o_http1_finalostream_t *self = (void *)_self;
- struct st_h2o_http1_conn_t *conn = (struct st_h2o_http1_conn_t *)req->conn;
- h2o_iovec_t *bufs = alloca(sizeof(h2o_iovec_t) * (inbufcnt + 1));
- int i;
- int bufcnt = 0;
-
- assert(self == &conn->_ostr_final);
-
- /* count bytes_sent if other ostreams haven't counted */
- if (req->bytes_counted_by_ostream == 0) {
- for (i = 0; i != inbufcnt; ++i) {
- req->bytes_sent += inbufs[i].len;
- }
- }
-
- if (!self->sent_headers) {
- conn->req.timestamps.response_start_at = *h2o_get_timestamp(conn->super.ctx, NULL, NULL);
- /* build headers and send */
- const char *connection = req->http1_is_persistent ? "keep-alive" : "close";
- bufs[bufcnt].base = h2o_mem_alloc_pool(
- &req->pool, flatten_headers_estimate_size(req, conn->super.ctx->globalconf->server_name.len + strlen(connection)));
- bufs[bufcnt].len = flatten_headers(bufs[bufcnt].base, req, connection);
- ++bufcnt;
- self->sent_headers = 1;
- }
- memcpy(bufs + bufcnt, inbufs, sizeof(h2o_iovec_t) * inbufcnt);
- bufcnt += inbufcnt;
-
- if (send_state == H2O_SEND_STATE_ERROR) {
- conn->req.http1_is_persistent = 0;
- }
-
- if (bufcnt != 0) {
- h2o_socket_write(conn->sock, bufs, bufcnt,
- h2o_send_state_is_in_progress(send_state) ? on_send_next_push : on_send_complete);
- } else {
- on_send_complete(conn->sock, 0);
- }
-}
-
-static socklen_t get_sockname(h2o_conn_t *_conn, struct sockaddr *sa)
-{
- struct st_h2o_http1_conn_t *conn = (void *)_conn;
- return h2o_socket_getsockname(conn->sock, sa);
-}
-
-static socklen_t get_peername(h2o_conn_t *_conn, struct sockaddr *sa)
-{
- struct st_h2o_http1_conn_t *conn = (void *)_conn;
- return h2o_socket_getpeername(conn->sock, sa);
-}
-
-static h2o_socket_t *get_socket(h2o_conn_t *_conn)
-{
- struct st_h2o_http1_conn_t *conn = (void *)_conn;
- return conn->sock;
-}
-
-#define DEFINE_TLS_LOGGER(name) \
- static h2o_iovec_t log_##name(h2o_req_t *req) \
- { \
- struct st_h2o_http1_conn_t *conn = (void *)req->conn; \
- return h2o_socket_log_ssl_##name(conn->sock, &req->pool); \
- }
-
-DEFINE_TLS_LOGGER(protocol_version)
-DEFINE_TLS_LOGGER(session_reused)
-DEFINE_TLS_LOGGER(cipher)
-DEFINE_TLS_LOGGER(cipher_bits)
-DEFINE_TLS_LOGGER(session_id)
-
-#undef DEFINE_TLS_LOGGER
-
-static h2o_iovec_t log_request_index(h2o_req_t *req)
-{
- struct st_h2o_http1_conn_t *conn = (void *)req->conn;
- char *s = h2o_mem_alloc_pool(&req->pool, sizeof(H2O_UINT64_LONGEST_STR));
- size_t len = sprintf(s, "%" PRIu64, conn->_req_index);
- return h2o_iovec_init(s, len);
-}
-
-static int foreach_request(h2o_context_t *ctx, int (*cb)(h2o_req_t *req, void *cbdata), void *cbdata)
-{
- h2o_linklist_t *node;
-
- for (node = ctx->http1._conns.next; node != &ctx->http1._conns; node = node->next) {
- struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, _conns, node);
- int ret = cb(&conn->req, cbdata);
- if (ret != 0)
- return ret;
- }
- return 0;
-}
-
-void h2o_http1_accept(h2o_accept_ctx_t *ctx, h2o_socket_t *sock, struct timeval connected_at)
-{
- static const h2o_conn_callbacks_t callbacks = {
- get_sockname, /* stringify address */
- get_peername, /* ditto */
- NULL, /* push */
- get_socket, /* get underlying socket */
- NULL, /* get debug state */
- {{
- {log_protocol_version, log_session_reused, log_cipher, log_cipher_bits, log_session_id}, /* ssl */
- {log_request_index}, /* http1 */
- {NULL} /* http2 */
- }}};
- struct st_h2o_http1_conn_t *conn = (void *)h2o_create_connection(sizeof(*conn), ctx->ctx, ctx->hosts, connected_at, &callbacks);
-
- /* zero-fill all properties expect req */
- memset((char *)conn + sizeof(conn->super), 0, offsetof(struct st_h2o_http1_conn_t, req) - sizeof(conn->super));
-
- /* init properties that need to be non-zero */
- conn->super.ctx = ctx->ctx;
- conn->super.hosts = ctx->hosts;
- conn->super.connected_at = connected_at;
- conn->super.callbacks = &callbacks;
- conn->sock = sock;
- sock->data = conn;
- h2o_linklist_insert(&ctx->ctx->http1._conns, &conn->_conns);
-
- init_request(conn, 0);
- reqread_start(conn);
-}
-
-void h2o_http1_upgrade(h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_http1_upgrade_cb on_complete, void *user_data)
-{
- struct st_h2o_http1_conn_t *conn = (void *)req->conn;
-
- assert(req->version <= 0x200); /* TODO find a better way to assert instanceof(req->conn) == struct st_h2o_http1_conn_t */
-
- h2o_iovec_t *bufs = alloca(sizeof(h2o_iovec_t) * (inbufcnt + 1));
-
- conn->upgrade.data = user_data;
- conn->upgrade.cb = on_complete;
-
- bufs[0].base =
- h2o_mem_alloc_pool(&conn->req.pool, flatten_headers_estimate_size(&conn->req, conn->super.ctx->globalconf->server_name.len +
- sizeof("upgrade") - 1));
- bufs[0].len = flatten_headers(bufs[0].base, &conn->req, "upgrade");
- h2o_memcpy(bufs + 1, inbufs, sizeof(h2o_iovec_t) * inbufcnt);
-
- h2o_socket_write(conn->sock, bufs, inbufcnt + 1, on_upgrade_complete);
-}
diff --git a/web/server/h2o/libh2o/lib/http2/cache_digests.c b/web/server/h2o/libh2o/lib/http2/cache_digests.c
deleted file mode 100644
index fa28bd238..000000000
--- a/web/server/h2o/libh2o/lib/http2/cache_digests.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <limits.h>
-#include <openssl/sha.h>
-#include <stdlib.h>
-#include "golombset.h"
-#include "h2o/string_.h"
-#include "h2o/cache_digests.h"
-
-struct st_h2o_cache_digests_frame_t {
- H2O_VECTOR(uint64_t) keys;
- unsigned capacity_bits;
-};
-
-static void dispose_frame_vector(h2o_cache_digests_frame_vector_t *v)
-{
- size_t i;
- for (i = 0; i != v->size; ++i)
- free(v->entries[i].keys.entries);
- free(v->entries);
-}
-
-static void dispose_digests(h2o_cache_digests_t *digests)
-{
- dispose_frame_vector(&digests->fresh.url_only);
- dispose_frame_vector(&digests->fresh.url_and_etag);
-}
-
-void h2o_cache_digests_destroy(h2o_cache_digests_t *digests)
-{
- dispose_digests(digests);
- free(digests);
-}
-
-static void load_digest(h2o_cache_digests_t **digests, const char *gcs_base64, size_t gcs_base64_len, int with_validators,
- int complete)
-{
- h2o_cache_digests_frame_t frame = {{NULL}};
- h2o_iovec_t gcs_bin;
- struct st_golombset_decode_t ctx = {NULL};
- uint64_t nbits, pbits;
-
- /* decode base64 */
- if ((gcs_bin = h2o_decode_base64url(NULL, gcs_base64, gcs_base64_len)).base == NULL)
- goto Exit;
-
- /* prepare GCS context */
- ctx.src = (void *)(gcs_bin.base - 1);
- ctx.src_max = (void *)(gcs_bin.base + gcs_bin.len);
- ctx.src_shift = 0;
-
- /* decode nbits and pbits */
- if (golombset_decode_bits(&ctx, 5, &nbits) != 0 || golombset_decode_bits(&ctx, 5, &pbits) != 0)
- goto Exit;
- frame.capacity_bits = (unsigned)(nbits + pbits);
-
- /* decode the values */
- uint64_t value = UINT64_MAX, decoded;
- while (golombset_decode_value(&ctx, (unsigned)pbits, &decoded) == 0) {
- value += decoded + 1;
- if (value >= (uint64_t)1 << frame.capacity_bits)
- goto Exit;
- h2o_vector_reserve(NULL, &frame.keys, frame.keys.size + 1);
- frame.keys.entries[frame.keys.size++] = value;
- }
-
- /* store the result */
- if (*digests == NULL) {
- *digests = h2o_mem_alloc(sizeof(**digests));
- **digests = (h2o_cache_digests_t){{{NULL}}};
- }
- h2o_cache_digests_frame_vector_t *target = with_validators ? &(*digests)->fresh.url_and_etag : &(*digests)->fresh.url_only;
- h2o_vector_reserve(NULL, target, target->size + 1);
- target->entries[target->size++] = frame;
- frame = (h2o_cache_digests_frame_t){{NULL}};
- (*digests)->fresh.complete = complete;
-
-Exit:
- free(frame.keys.entries);
- free(gcs_bin.base);
-}
-
-void h2o_cache_digests_load_header(h2o_cache_digests_t **digests, const char *value, size_t len)
-{
- h2o_iovec_t iter = h2o_iovec_init(value, len);
- const char *token;
- size_t token_len;
-
- do {
- const char *gcs_base64;
- size_t gcs_base64_len;
- int reset = 0, validators = 0, complete = 0, skip = 0;
- h2o_iovec_t token_value;
-
- if ((gcs_base64 = h2o_next_token(&iter, ';', &gcs_base64_len, NULL)) == NULL)
- return;
- while ((token = h2o_next_token(&iter, ';', &token_len, &token_value)) != NULL &&
- !h2o_memis(token, token_len, H2O_STRLIT(","))) {
- if (h2o_lcstris(token, token_len, H2O_STRLIT("reset"))) {
- reset = 1;
- } else if (h2o_lcstris(token, token_len, H2O_STRLIT("validators"))) {
- validators = 1;
- } else if (h2o_lcstris(token, token_len, H2O_STRLIT("complete"))) {
- complete = 1;
- } else {
- skip = 1;
- }
- }
-
- if (reset && *digests != NULL) {
- h2o_cache_digests_destroy(*digests);
- *digests = NULL;
- }
-
- if (skip) {
- /* not supported for the time being */
- } else {
- load_digest(digests, gcs_base64, gcs_base64_len, validators, complete);
- }
- } while (token != NULL);
-}
-
-static uint64_t calc_hash(const char *url, size_t url_len, const char *etag, size_t etag_len)
-{
- SHA256_CTX ctx;
- union {
- unsigned char bytes[SHA256_DIGEST_LENGTH];
- uint64_t u64;
- } md;
-
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, url, url_len);
- SHA256_Update(&ctx, etag, etag_len);
- SHA256_Final(md.bytes, &ctx);
-
- if (*(uint16_t *)"\xde\xad" == 0xdead)
- return md.u64;
- else
- return __builtin_bswap64(md.u64);
-}
-
-static int cmp_key(const void *_x, const void *_y)
-{
- uint64_t x = *(uint64_t *)_x, y = *(uint64_t *)_y;
-
- if (x < y) {
- return -1;
- } else if (x > y) {
- return 1;
- } else {
- return 0;
- }
-}
-
-static int lookup(h2o_cache_digests_frame_vector_t *vector, const char *url, size_t url_len, const char *etag, size_t etag_len,
- int is_fresh, int is_complete)
-{
- if (vector->size != 0) {
- uint64_t hash = calc_hash(url, url_len, etag, etag_len);
- size_t i = 0;
- do {
- h2o_cache_digests_frame_t *frame = vector->entries + i;
- uint64_t key = hash >> (64 - frame->capacity_bits);
- if (frame->keys.entries != NULL &&
- bsearch(&key, frame->keys.entries, frame->keys.size, sizeof(frame->keys.entries[0]), cmp_key) != NULL)
- return is_fresh ? H2O_CACHE_DIGESTS_STATE_FRESH : H2O_CACHE_DIGESTS_STATE_STALE;
- } while (++i != vector->size);
- }
-
- return is_complete ? H2O_CACHE_DIGESTS_STATE_NOT_CACHED : H2O_CACHE_DIGESTS_STATE_UNKNOWN;
-}
-
-h2o_cache_digests_state_t h2o_cache_digests_lookup_by_url(h2o_cache_digests_t *digests, const char *url, size_t url_len)
-{
- return lookup(&digests->fresh.url_only, url, url_len, "", 0, 1, digests->fresh.complete);
-}
-
-h2o_cache_digests_state_t h2o_cache_digests_lookup_by_url_and_etag(h2o_cache_digests_t *digests, const char *url, size_t url_len,
- const char *etag, size_t etag_len)
-{
- return lookup(&digests->fresh.url_and_etag, url, url_len, etag, etag_len, 1, digests->fresh.complete);
-}
diff --git a/web/server/h2o/libh2o/lib/http2/casper.c b/web/server/h2o/libh2o/lib/http2/casper.c
deleted file mode 100644
index 56e00d71f..000000000
--- a/web/server/h2o/libh2o/lib/http2/casper.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <openssl/sha.h>
-#include "golombset.h"
-#include "h2o/string_.h"
-#include "h2o/http2_casper.h"
-
-#define COOKIE_NAME "h2o_casper"
-#define COOKIE_ATTRIBUTES "; Path=/; Expires=Tue, 01 Jan 2030 00:00:00 GMT; Secure"
-
-struct st_h2o_http2_casper_t {
- H2O_VECTOR(uint64_t) keys;
- unsigned capacity_bits;
- unsigned remainder_bits;
- h2o_iovec_t cookie_cache;
-};
-
-static unsigned calc_key(h2o_http2_casper_t *casper, const char *path, size_t path_len)
-{
- SHA_CTX ctx;
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, path, path_len);
-
- union {
- unsigned key;
- unsigned char bytes[SHA_DIGEST_LENGTH];
- } md;
- SHA1_Final(md.bytes, &ctx);
-
- return md.key & ((1 << casper->capacity_bits) - 1);
-}
-
-h2o_http2_casper_t *h2o_http2_casper_create(unsigned capacity_bits, unsigned remainder_bits)
-{
- h2o_http2_casper_t *casper = h2o_mem_alloc(sizeof(*casper));
-
- memset(&casper->keys, 0, sizeof(casper->keys));
- casper->capacity_bits = capacity_bits;
- casper->remainder_bits = remainder_bits;
- casper->cookie_cache = (h2o_iovec_t){NULL};
-
- return casper;
-}
-
-void h2o_http2_casper_destroy(h2o_http2_casper_t *casper)
-{
- free(casper->keys.entries);
- free(casper->cookie_cache.base);
- free(casper);
-}
-
-size_t h2o_http2_casper_num_entries(h2o_http2_casper_t *casper)
-{
- return casper->keys.size;
-}
-
-int h2o_http2_casper_lookup(h2o_http2_casper_t *casper, const char *path, size_t path_len, int set)
-{
- unsigned key = calc_key(casper, path, path_len);
- size_t i;
-
- /* FIXME use binary search */
- for (i = 0; i != casper->keys.size; ++i)
- if (key <= casper->keys.entries[i])
- break;
- if (i != casper->keys.size && key == casper->keys.entries[i])
- return 1;
- if (!set)
- return 0;
-
- /* we need to set a new value */
- free(casper->cookie_cache.base);
- casper->cookie_cache = (h2o_iovec_t){NULL};
- h2o_vector_reserve(NULL, &casper->keys, casper->keys.size + 1);
- memmove(casper->keys.entries + i + 1, casper->keys.entries + i, (casper->keys.size - i) * sizeof(casper->keys.entries[0]));
- ++casper->keys.size;
- casper->keys.entries[i] = key;
- return 0;
-}
-
-void h2o_http2_casper_consume_cookie(h2o_http2_casper_t *casper, const char *cookie, size_t cookie_len)
-{
- h2o_iovec_t binary = {NULL};
- uint64_t tiny_keys_buf[128], *keys = tiny_keys_buf;
-
- /* check the name of the cookie */
- if (!(cookie_len > sizeof(COOKIE_NAME "=") - 1 && memcmp(cookie, H2O_STRLIT(COOKIE_NAME "=")) == 0))
- goto Exit;
-
- /* base64 decode */
- if ((binary = h2o_decode_base64url(NULL, cookie + sizeof(COOKIE_NAME "=") - 1, cookie_len - (sizeof(COOKIE_NAME "=") - 1)))
- .base == NULL)
- goto Exit;
-
- /* decode GCS, either using tiny_keys_buf or using heap */
- size_t capacity = sizeof(tiny_keys_buf) / sizeof(tiny_keys_buf[0]), num_keys;
- while (num_keys = capacity, golombset_decode(casper->remainder_bits, binary.base, binary.len, keys, &num_keys) != 0) {
- if (keys != tiny_keys_buf) {
- free(keys);
- keys = tiny_keys_buf; /* reset to something that would not trigger call to free(3) */
- }
- if (capacity >= (size_t)1 << casper->capacity_bits)
- goto Exit;
- capacity *= 2;
- keys = h2o_mem_alloc(capacity * sizeof(*keys));
- }
-
- /* copy or merge the entries */
- if (num_keys == 0) {
- /* nothing to do */
- } else if (casper->keys.size == 0) {
- h2o_vector_reserve(NULL, &casper->keys, num_keys);
- memcpy(casper->keys.entries, keys, num_keys * sizeof(*keys));
- casper->keys.size = num_keys;
- } else {
- uint64_t *orig_keys = casper->keys.entries;
- size_t num_orig_keys = casper->keys.size, orig_index = 0, new_index = 0;
- memset(&casper->keys, 0, sizeof(casper->keys));
- h2o_vector_reserve(NULL, &casper->keys, num_keys + num_orig_keys);
- do {
- if (orig_keys[orig_index] < keys[new_index]) {
- casper->keys.entries[casper->keys.size++] = orig_keys[orig_index++];
- } else if (orig_keys[orig_index] > keys[new_index]) {
- casper->keys.entries[casper->keys.size++] = keys[new_index++];
- } else {
- casper->keys.entries[casper->keys.size++] = orig_keys[orig_index];
- ++orig_index;
- ++new_index;
- }
- } while (orig_index != num_orig_keys && new_index != num_keys);
- if (orig_index != num_orig_keys) {
- do {
- casper->keys.entries[casper->keys.size++] = orig_keys[orig_index++];
- } while (orig_index != num_orig_keys);
- } else if (new_index != num_keys) {
- do {
- casper->keys.entries[casper->keys.size++] = keys[new_index++];
- } while (new_index != num_keys);
- }
- free(orig_keys);
- }
-
-Exit:
- if (keys != tiny_keys_buf)
- free(keys);
- free(binary.base);
-}
-
-static size_t append_str(char *dst, const char *s, size_t l)
-{
- memcpy(dst, s, l);
- return l;
-}
-
-h2o_iovec_t h2o_http2_casper_get_cookie(h2o_http2_casper_t *casper)
-{
- if (casper->cookie_cache.base != NULL)
- return casper->cookie_cache;
-
- if (casper->keys.size == 0)
- return (h2o_iovec_t){NULL};
-
- /* encode as binary */
- char tiny_bin_buf[128], *bin_buf = tiny_bin_buf;
- size_t bin_capacity = sizeof(tiny_bin_buf), bin_size;
- while (bin_size = bin_capacity,
- golombset_encode(casper->remainder_bits, casper->keys.entries, casper->keys.size, bin_buf, &bin_size) != 0) {
- if (bin_buf != tiny_bin_buf)
- free(bin_buf);
- bin_capacity *= 2;
- bin_buf = h2o_mem_alloc(bin_capacity);
- }
-
- char *header_bytes = h2o_mem_alloc(sizeof(COOKIE_NAME "=" COOKIE_ATTRIBUTES) - 1 + (bin_size + 3) * 4 / 3);
- size_t header_len = 0;
-
- header_len += append_str(header_bytes + header_len, H2O_STRLIT(COOKIE_NAME "="));
- header_len += h2o_base64_encode(header_bytes + header_len, bin_buf, bin_size, 1);
- header_len += append_str(header_bytes + header_len, H2O_STRLIT(COOKIE_ATTRIBUTES));
-
- if (bin_buf != tiny_bin_buf)
- free(bin_buf);
-
- casper->cookie_cache = h2o_iovec_init(header_bytes, header_len);
- return casper->cookie_cache;
-}
diff --git a/web/server/h2o/libh2o/lib/http2/connection.c b/web/server/h2o/libh2o/lib/http2/connection.c
deleted file mode 100644
index e2da29304..000000000
--- a/web/server/h2o/libh2o/lib/http2/connection.c
+++ /dev/null
@@ -1,1419 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Fastly, Inc.
- *
- * 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 <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "h2o.h"
-#include "h2o/http1.h"
-#include "h2o/http2.h"
-#include "h2o/http2_internal.h"
-
-static const h2o_iovec_t CONNECTION_PREFACE = {H2O_STRLIT("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")};
-
-const h2o_http2_priority_t h2o_http2_default_priority = {
- 0, /* exclusive */
- 0, /* dependency */
- 16 /* weight */
-};
-
-const h2o_http2_settings_t H2O_HTTP2_SETTINGS_HOST = {
- 4096, /* header_table_size */
- 0, /* enable_push (clients are never allowed to initiate server push; RFC 7540 Section 8.2) */
- 100, /* max_concurrent_streams */
- 16777216, /* initial_window_size */
- 16384 /* max_frame_size */
-};
-
-static const h2o_iovec_t SETTINGS_HOST_BIN = {H2O_STRLIT("\x00\x00\x0c" /* frame size */
- "\x04" /* settings frame */
- "\x00" /* no flags */
- "\x00\x00\x00\x00" /* stream id */
- "\x00\x03"
- "\x00\x00\x00\x64" /* max_concurrent_streams = 100 */
- "\x00\x04"
- "\x01\x00\x00\x00" /* initial_window_size = 16777216 */
- )};
-
-static __thread h2o_buffer_prototype_t wbuf_buffer_prototype = {{16}, {H2O_HTTP2_DEFAULT_OUTBUF_SIZE}};
-
-static void initiate_graceful_shutdown(h2o_context_t *ctx);
-static void close_connection_now(h2o_http2_conn_t *conn);
-static int close_connection(h2o_http2_conn_t *conn);
-static ssize_t expect_default(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc);
-static void do_emit_writereq(h2o_http2_conn_t *conn);
-static void on_read(h2o_socket_t *sock, const char *err);
-static void push_path(h2o_req_t *src_req, const char *abspath, size_t abspath_len);
-static int foreach_request(h2o_context_t *ctx, int (*cb)(h2o_req_t *req, void *cbdata), void *cbdata);
-static void stream_send_error(h2o_http2_conn_t *conn, uint32_t stream_id, int errnum);
-
-const h2o_protocol_callbacks_t H2O_HTTP2_CALLBACKS = {initiate_graceful_shutdown, foreach_request};
-
-static int is_idle_stream_id(h2o_http2_conn_t *conn, uint32_t stream_id)
-{
- return (h2o_http2_stream_is_push(stream_id) ? conn->push_stream_ids.max_open : conn->pull_stream_ids.max_open) < stream_id;
-}
-
-static void enqueue_goaway(h2o_http2_conn_t *conn, int errnum, h2o_iovec_t additional_data)
-{
- if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
- /* http2 spec allows sending GOAWAY more than once (for one reason since errors may arise after sending the first one) */
- h2o_http2_encode_goaway_frame(&conn->_write.buf, conn->pull_stream_ids.max_open, errnum, additional_data);
- h2o_http2_conn_request_write(conn);
- conn->state = H2O_HTTP2_CONN_STATE_HALF_CLOSED;
- }
-}
-
-static void graceful_shutdown_close_stragglers(h2o_timeout_entry_t *entry)
-{
- h2o_context_t *ctx = H2O_STRUCT_FROM_MEMBER(h2o_context_t, http2._graceful_shutdown_timeout, entry);
- h2o_linklist_t *node, *next;
-
- /* We've sent two GOAWAY frames, close the remaining connections */
- for (node = ctx->http2._conns.next; node != &ctx->http2._conns; node = next) {
- h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _conns, node);
- next = node->next;
- close_connection(conn);
- }
-}
-
-static void graceful_shutdown_resend_goaway(h2o_timeout_entry_t *entry)
-{
- h2o_context_t *ctx = H2O_STRUCT_FROM_MEMBER(h2o_context_t, http2._graceful_shutdown_timeout, entry);
- h2o_linklist_t *node;
- int do_close_stragglers = 0;
-
- for (node = ctx->http2._conns.next; node != &ctx->http2._conns; node = node->next) {
- h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _conns, node);
- if (conn->state < H2O_HTTP2_CONN_STATE_HALF_CLOSED) {
- enqueue_goaway(conn, H2O_HTTP2_ERROR_NONE, (h2o_iovec_t){NULL});
- do_close_stragglers = 1;
- }
- }
-
- /* After waiting a second, we still had active connections. If configured, wait one
- * final timeout before closing the connections */
- if (do_close_stragglers && ctx->globalconf->http2.graceful_shutdown_timeout) {
- ctx->http2._graceful_shutdown_timeout.cb = graceful_shutdown_close_stragglers;
- h2o_timeout_link(ctx->loop, &ctx->http2.graceful_shutdown_timeout, &ctx->http2._graceful_shutdown_timeout);
- }
-}
-
-static void initiate_graceful_shutdown(h2o_context_t *ctx)
-{
- /* draft-16 6.8
- * A server that is attempting to gracefully shut down a connection SHOULD send an initial GOAWAY frame with the last stream
- * identifier set to 231-1 and a NO_ERROR code. This signals to the client that a shutdown is imminent and that no further
- * requests can be initiated. After waiting at least one round trip time, the server can send another GOAWAY frame with an
- * updated last stream identifier. This ensures that a connection can be cleanly shut down without losing requests.
- */
- h2o_linklist_t *node;
-
- /* only doit once */
- if (ctx->http2._graceful_shutdown_timeout.cb != NULL)
- return;
- ctx->http2._graceful_shutdown_timeout.cb = graceful_shutdown_resend_goaway;
-
- for (node = ctx->http2._conns.next; node != &ctx->http2._conns; node = node->next) {
- h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _conns, node);
- if (conn->state < H2O_HTTP2_CONN_STATE_HALF_CLOSED) {
- h2o_http2_encode_goaway_frame(&conn->_write.buf, INT32_MAX, H2O_HTTP2_ERROR_NONE,
- (h2o_iovec_t){H2O_STRLIT("graceful shutdown")});
- h2o_http2_conn_request_write(conn);
- }
- }
- h2o_timeout_link(ctx->loop, &ctx->one_sec_timeout, &ctx->http2._graceful_shutdown_timeout);
-}
-
-static void on_idle_timeout(h2o_timeout_entry_t *entry)
-{
- h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _timeout_entry, entry);
-
- enqueue_goaway(conn, H2O_HTTP2_ERROR_NONE, h2o_iovec_init(H2O_STRLIT("idle timeout")));
- if (conn->_write.buf_in_flight != NULL) {
- close_connection_now(conn);
- } else {
- enqueue_goaway(conn, H2O_HTTP2_ERROR_NONE, h2o_iovec_init(H2O_STRLIT("idle timeout")));
- close_connection(conn);
- }
-}
-
-static void update_idle_timeout(h2o_http2_conn_t *conn)
-{
- h2o_timeout_unlink(&conn->_timeout_entry);
-
- if (conn->num_streams.pull.half_closed + conn->num_streams.push.half_closed == 0) {
- assert(h2o_linklist_is_empty(&conn->_pending_reqs));
- conn->_timeout_entry.cb = on_idle_timeout;
- h2o_timeout_link(conn->super.ctx->loop, &conn->super.ctx->http2.idle_timeout, &conn->_timeout_entry);
- }
-}
-
-static int can_run_requests(h2o_http2_conn_t *conn)
-{
- return conn->num_streams.pull.half_closed + conn->num_streams.push.half_closed <
- conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection;
-}
-
-static void run_pending_requests(h2o_http2_conn_t *conn)
-{
- while (!h2o_linklist_is_empty(&conn->_pending_reqs) && can_run_requests(conn)) {
- /* fetch and detach a pending stream */
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _refs.link, conn->_pending_reqs.next);
- h2o_linklist_unlink(&stream->_refs.link);
- /* handle it */
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
- if (!h2o_http2_stream_is_push(stream->stream_id) && conn->pull_stream_ids.max_processed < stream->stream_id)
- conn->pull_stream_ids.max_processed = stream->stream_id;
- h2o_process_request(&stream->req);
- }
-}
-
-static void execute_or_enqueue_request(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- assert(stream->state < H2O_HTTP2_STREAM_STATE_REQ_PENDING);
-
- if (stream->_req_body != NULL && stream->_expected_content_length != SIZE_MAX &&
- stream->_req_body->size != stream->_expected_content_length) {
- stream_send_error(conn, stream->stream_id, H2O_HTTP2_ERROR_PROTOCOL);
- h2o_http2_stream_reset(conn, stream);
- return;
- }
-
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
-
- /* TODO schedule the pending reqs using the scheduler */
- h2o_linklist_insert(&conn->_pending_reqs, &stream->_refs.link);
-
- run_pending_requests(conn);
- update_idle_timeout(conn);
-}
-
-void h2o_http2_conn_register_stream(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- khiter_t iter;
- int r;
-
- iter = kh_put(h2o_http2_stream_t, conn->streams, stream->stream_id, &r);
- assert(iter != kh_end(conn->streams));
- kh_val(conn->streams, iter) = stream;
-}
-
-void h2o_http2_conn_unregister_stream(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- khiter_t iter = kh_get(h2o_http2_stream_t, conn->streams, stream->stream_id);
- assert(iter != kh_end(conn->streams));
- kh_del(h2o_http2_stream_t, conn->streams, iter);
-
- assert(h2o_http2_scheduler_is_open(&stream->_refs.scheduler));
- h2o_http2_scheduler_close(&stream->_refs.scheduler);
-
- switch (stream->state) {
- case H2O_HTTP2_STREAM_STATE_IDLE:
- case H2O_HTTP2_STREAM_STATE_RECV_HEADERS:
- case H2O_HTTP2_STREAM_STATE_RECV_BODY:
- assert(!h2o_linklist_is_linked(&stream->_refs.link));
- break;
- case H2O_HTTP2_STREAM_STATE_REQ_PENDING:
- assert(h2o_linklist_is_linked(&stream->_refs.link));
- h2o_linklist_unlink(&stream->_refs.link);
- break;
- case H2O_HTTP2_STREAM_STATE_SEND_HEADERS:
- case H2O_HTTP2_STREAM_STATE_SEND_BODY:
- case H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL:
- case H2O_HTTP2_STREAM_STATE_END_STREAM:
- if (h2o_linklist_is_linked(&stream->_refs.link))
- h2o_linklist_unlink(&stream->_refs.link);
- break;
- }
- if (stream->state != H2O_HTTP2_STREAM_STATE_END_STREAM)
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_END_STREAM);
-
- if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
- run_pending_requests(conn);
- update_idle_timeout(conn);
- }
-}
-
-void close_connection_now(h2o_http2_conn_t *conn)
-{
- h2o_http2_stream_t *stream;
-
- assert(!h2o_timeout_is_linked(&conn->_write.timeout_entry));
-
- kh_foreach_value(conn->streams, stream, { h2o_http2_stream_close(conn, stream); });
- assert(conn->num_streams.pull.open == 0);
- assert(conn->num_streams.pull.half_closed == 0);
- assert(conn->num_streams.pull.send_body == 0);
- assert(conn->num_streams.push.half_closed == 0);
- assert(conn->num_streams.push.send_body == 0);
- assert(conn->num_streams.priority.open == 0);
- kh_destroy(h2o_http2_stream_t, conn->streams);
- assert(conn->_http1_req_input == NULL);
- h2o_hpack_dispose_header_table(&conn->_input_header_table);
- h2o_hpack_dispose_header_table(&conn->_output_header_table);
- assert(h2o_linklist_is_empty(&conn->_pending_reqs));
- h2o_timeout_unlink(&conn->_timeout_entry);
- h2o_buffer_dispose(&conn->_write.buf);
- if (conn->_write.buf_in_flight != NULL)
- h2o_buffer_dispose(&conn->_write.buf_in_flight);
- h2o_http2_scheduler_dispose(&conn->scheduler);
- assert(h2o_linklist_is_empty(&conn->_write.streams_to_proceed));
- assert(!h2o_timeout_is_linked(&conn->_write.timeout_entry));
- if (conn->_headers_unparsed != NULL)
- h2o_buffer_dispose(&conn->_headers_unparsed);
- if (conn->push_memo != NULL)
- h2o_cache_destroy(conn->push_memo);
- if (conn->casper != NULL)
- h2o_http2_casper_destroy(conn->casper);
- h2o_linklist_unlink(&conn->_conns);
-
- if (conn->sock != NULL)
- h2o_socket_close(conn->sock);
- free(conn);
-}
-
-int close_connection(h2o_http2_conn_t *conn)
-{
- conn->state = H2O_HTTP2_CONN_STATE_IS_CLOSING;
-
- if (conn->_write.buf_in_flight != NULL || h2o_timeout_is_linked(&conn->_write.timeout_entry)) {
- /* there is a pending write, let on_write_complete actually close the connection */
- } else {
- close_connection_now(conn);
- return -1;
- }
- return 0;
-}
-
-static void stream_send_error(h2o_http2_conn_t *conn, uint32_t stream_id, int errnum)
-{
- assert(stream_id != 0);
- assert(conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING);
-
- conn->super.ctx->http2.events.protocol_level_errors[-errnum]++;
-
- h2o_http2_encode_rst_stream_frame(&conn->_write.buf, stream_id, -errnum);
- h2o_http2_conn_request_write(conn);
-}
-
-static void request_gathered_write(h2o_http2_conn_t *conn)
-{
- assert(conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING);
- if (conn->sock->_cb.write == NULL && !h2o_timeout_is_linked(&conn->_write.timeout_entry))
- h2o_timeout_link(conn->super.ctx->loop, &conn->super.ctx->zero_timeout, &conn->_write.timeout_entry);
-}
-
-static int update_stream_output_window(h2o_http2_stream_t *stream, ssize_t delta)
-{
- ssize_t cur = h2o_http2_window_get_window(&stream->output_window);
- if (h2o_http2_window_update(&stream->output_window, delta) != 0)
- return -1;
- if (cur <= 0 && h2o_http2_window_get_window(&stream->output_window) > 0 &&
- (h2o_http2_stream_has_pending_data(stream) || stream->state >= H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL)) {
- assert(!h2o_linklist_is_linked(&stream->_refs.link));
- h2o_http2_scheduler_activate(&stream->_refs.scheduler);
- }
- return 0;
-}
-
-static int handle_incoming_request(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, const uint8_t *src, size_t len,
- const char **err_desc)
-{
- int ret, header_exists_map;
-
- assert(stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS);
-
- header_exists_map = 0;
- if ((ret = h2o_hpack_parse_headers(&stream->req, &conn->_input_header_table, src, len, &header_exists_map,
- &stream->_expected_content_length, &stream->cache_digests, err_desc)) != 0) {
- /* all errors except invalid-header-char are connection errors */
- if (ret != H2O_HTTP2_ERROR_INVALID_HEADER_CHAR)
- return ret;
- }
-
- /* handle stream-level errors */
-#define EXPECTED_MAP \
- (H2O_HPACK_PARSE_HEADERS_METHOD_EXISTS | H2O_HPACK_PARSE_HEADERS_PATH_EXISTS | H2O_HPACK_PARSE_HEADERS_SCHEME_EXISTS)
- if ((header_exists_map & EXPECTED_MAP) != EXPECTED_MAP) {
- ret = H2O_HTTP2_ERROR_PROTOCOL;
- goto SendRSTStream;
- }
-#undef EXPECTED_MAP
- if (conn->num_streams.pull.open > H2O_HTTP2_SETTINGS_HOST.max_concurrent_streams) {
- ret = H2O_HTTP2_ERROR_REFUSED_STREAM;
- goto SendRSTStream;
- }
-
- /* handle request to send response */
- if (ret != 0) {
- assert(ret == H2O_HTTP2_ERROR_INVALID_HEADER_CHAR);
- /* fast forward the stream's state so that we can start sending the response */
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
- h2o_send_error_400(&stream->req, "Invalid Headers", *err_desc, 0);
- return 0;
- }
-
- if (stream->_req_body == NULL) {
- execute_or_enqueue_request(conn, stream);
- } else {
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_RECV_BODY);
- }
- return 0;
-
-SendRSTStream:
- stream_send_error(conn, stream->stream_id, ret);
- h2o_http2_stream_reset(conn, stream);
- return 0;
-}
-
-static int handle_trailing_headers(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, const uint8_t *src, size_t len,
- const char **err_desc)
-{
- size_t dummy_content_length;
- int ret;
-
- assert(stream->state == H2O_HTTP2_STREAM_STATE_RECV_BODY);
-
- if ((ret = h2o_hpack_parse_headers(&stream->req, &conn->_input_header_table, src, len, NULL, &dummy_content_length, NULL,
- err_desc)) != 0)
- return ret;
-
- execute_or_enqueue_request(conn, stream);
- return 0;
-}
-
-static ssize_t expect_continuation_of_headers(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
-{
- h2o_http2_frame_t frame;
- ssize_t ret;
- h2o_http2_stream_t *stream;
- int hret;
-
- if ((ret = h2o_http2_decode_frame(&frame, src, len, &H2O_HTTP2_SETTINGS_HOST, err_desc)) < 0)
- return ret;
- if (frame.type != H2O_HTTP2_FRAME_TYPE_CONTINUATION) {
- *err_desc = "expected CONTINUATION frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
-
- if (conn->state >= H2O_HTTP2_CONN_STATE_HALF_CLOSED)
- return 0;
-
- if ((stream = h2o_http2_conn_get_stream(conn, frame.stream_id)) == NULL ||
- !(stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS || stream->state == H2O_HTTP2_STREAM_STATE_RECV_BODY)) {
- *err_desc = "unexpected stream id in CONTINUATION frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
-
- if (conn->_headers_unparsed->size + frame.length <= H2O_MAX_REQLEN) {
- h2o_buffer_reserve(&conn->_headers_unparsed, frame.length);
- memcpy(conn->_headers_unparsed->bytes + conn->_headers_unparsed->size, frame.payload, frame.length);
- conn->_headers_unparsed->size += frame.length;
-
- if ((frame.flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) != 0) {
- conn->_read_expect = expect_default;
- if (stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS) {
- hret = handle_incoming_request(conn, stream, (const uint8_t *)conn->_headers_unparsed->bytes,
- conn->_headers_unparsed->size, err_desc);
- } else {
- hret = handle_trailing_headers(conn, stream, (const uint8_t *)conn->_headers_unparsed->bytes,
- conn->_headers_unparsed->size, err_desc);
- }
- if (hret != 0)
- ret = hret;
- h2o_buffer_dispose(&conn->_headers_unparsed);
- conn->_headers_unparsed = NULL;
- }
- } else {
- /* request is too large (TODO log) */
- stream_send_error(conn, stream->stream_id, H2O_HTTP2_ERROR_REFUSED_STREAM);
- h2o_http2_stream_reset(conn, stream);
- }
-
- return ret;
-}
-
-static void update_input_window(h2o_http2_conn_t *conn, uint32_t stream_id, h2o_http2_window_t *window, size_t consumed)
-{
- h2o_http2_window_consume_window(window, consumed);
- if (h2o_http2_window_get_window(window) * 2 < H2O_HTTP2_SETTINGS_HOST.initial_window_size) {
- int32_t delta = (int32_t)(H2O_HTTP2_SETTINGS_HOST.initial_window_size - h2o_http2_window_get_window(window));
- h2o_http2_encode_window_update_frame(&conn->_write.buf, stream_id, delta);
- h2o_http2_conn_request_write(conn);
- h2o_http2_window_update(window, delta);
- }
-}
-
-static void set_priority(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, const h2o_http2_priority_t *priority,
- int scheduler_is_open)
-{
- h2o_http2_scheduler_node_t *parent_sched;
-
- /* determine the parent */
- if (priority->dependency != 0) {
- h2o_http2_stream_t *parent_stream = h2o_http2_conn_get_stream(conn, priority->dependency);
- if (parent_stream != NULL) {
- parent_sched = &parent_stream->_refs.scheduler.node;
- } else {
- /* A dependency on a stream that is not currently in the tree - such as a stream in the "idle" state - results in that
- * stream being given a default priority. (RFC 7540 5.3.1)
- * It is possible for a stream to become closed while prioritization information that creates a dependency on that
- * stream is in transit. If a stream identified in a dependency has no associated priority information, then the
- * dependent stream is instead assigned a default priority. (RFC 7540 5.3.4)
- */
- parent_sched = &conn->scheduler;
- priority = &h2o_http2_default_priority;
- }
- } else {
- parent_sched = &conn->scheduler;
- }
-
- /* setup the scheduler */
- if (!scheduler_is_open) {
- h2o_http2_scheduler_open(&stream->_refs.scheduler, parent_sched, priority->weight, priority->exclusive);
- } else {
- h2o_http2_scheduler_rebind(&stream->_refs.scheduler, parent_sched, priority->weight, priority->exclusive);
- }
-}
-
-static int handle_data_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
-{
- h2o_http2_data_payload_t payload;
- h2o_http2_stream_t *stream;
- int ret;
-
- if ((ret = h2o_http2_decode_data_payload(&payload, frame, err_desc)) != 0)
- return ret;
-
- if (conn->state >= H2O_HTTP2_CONN_STATE_HALF_CLOSED)
- return 0;
-
- stream = h2o_http2_conn_get_stream(conn, frame->stream_id);
-
- /* save the input in the request body buffer, or send error (and close the stream) */
- if (stream == NULL) {
- if (frame->stream_id <= conn->pull_stream_ids.max_open) {
- stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_STREAM_CLOSED);
- } else {
- *err_desc = "invalid DATA frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- } else if (stream->state != H2O_HTTP2_STREAM_STATE_RECV_BODY) {
- stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_STREAM_CLOSED);
- h2o_http2_stream_reset(conn, stream);
- stream = NULL;
- } else if (stream->_req_body->size + payload.length > conn->super.ctx->globalconf->max_request_entity_size) {
- stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_REFUSED_STREAM);
- h2o_http2_stream_reset(conn, stream);
- stream = NULL;
- } else {
- h2o_iovec_t buf = h2o_buffer_reserve(&stream->_req_body, payload.length);
- if (buf.base != NULL) {
- memcpy(buf.base, payload.data, payload.length);
- stream->_req_body->size += payload.length;
- /* handle request if request body is complete */
- if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0) {
- stream->req.entity = h2o_iovec_init(stream->_req_body->bytes, stream->_req_body->size);
- execute_or_enqueue_request(conn, stream);
- stream = NULL; /* no need to send window update for this stream */
- }
- } else {
- /* memory allocation failed */
- stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_STREAM_CLOSED);
- h2o_http2_stream_reset(conn, stream);
- stream = NULL;
- }
- }
-
- /* consume buffer (and set window_update) */
- update_input_window(conn, 0, &conn->_input_window, frame->length);
- if (stream != NULL)
- update_input_window(conn, stream->stream_id, &stream->input_window, frame->length);
-
- return 0;
-}
-
-static int handle_headers_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
-{
- h2o_http2_headers_payload_t payload;
- h2o_http2_stream_t *stream;
- int ret;
-
- /* decode */
- if ((ret = h2o_http2_decode_headers_payload(&payload, frame, err_desc)) != 0)
- return ret;
- if ((frame->stream_id & 1) == 0) {
- *err_desc = "invalid stream id in HEADERS frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- if (!(conn->pull_stream_ids.max_open < frame->stream_id)) {
- if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) != NULL &&
- stream->state == H2O_HTTP2_STREAM_STATE_RECV_BODY) {
- /* is a trailer */
- if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) == 0) {
- *err_desc = "trailing HEADERS frame MUST have END_STREAM flag set";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- stream->req.entity = h2o_iovec_init(stream->_req_body->bytes, stream->_req_body->size);
- if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) == 0)
- goto PREPARE_FOR_CONTINUATION;
- return handle_trailing_headers(conn, stream, payload.headers, payload.headers_len, err_desc);
- } else if (!stream || stream->state != H2O_HTTP2_STREAM_STATE_IDLE) {
- /* it's legit that stream exists and is IDLE if a PRIORITY frame was received earlier */
- *err_desc = "invalid stream id in HEADERS frame";
- return H2O_HTTP2_ERROR_STREAM_CLOSED;
- }
- }
- if (frame->stream_id == payload.priority.dependency) {
- *err_desc = "stream cannot depend on itself";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
-
- if (conn->state >= H2O_HTTP2_CONN_STATE_HALF_CLOSED)
- return 0;
-
- /* open or determine the stream and prepare */
- if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) != NULL) {
- if ((frame->flags & H2O_HTTP2_FRAME_FLAG_PRIORITY) != 0) {
- set_priority(conn, stream, &payload.priority, 1);
- stream->received_priority = payload.priority;
- }
- } else {
- stream = h2o_http2_stream_open(conn, frame->stream_id, NULL, &payload.priority);
- set_priority(conn, stream, &payload.priority, 0);
- }
- h2o_http2_stream_prepare_for_request(conn, stream);
-
- /* setup container for request body if it is expected to arrive */
- if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) == 0)
- h2o_buffer_init(&stream->_req_body, &h2o_socket_buffer_prototype);
-
- if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) != 0) {
- /* request is complete, handle it */
- return handle_incoming_request(conn, stream, payload.headers, payload.headers_len, err_desc);
- }
-
-PREPARE_FOR_CONTINUATION:
- /* request is not complete, store in buffer */
- conn->_read_expect = expect_continuation_of_headers;
- h2o_buffer_init(&conn->_headers_unparsed, &h2o_socket_buffer_prototype);
- h2o_buffer_reserve(&conn->_headers_unparsed, payload.headers_len);
- memcpy(conn->_headers_unparsed->bytes, payload.headers, payload.headers_len);
- conn->_headers_unparsed->size = payload.headers_len;
- return 0;
-}
-
-static int handle_priority_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
-{
- h2o_http2_priority_t payload;
- h2o_http2_stream_t *stream;
- int ret;
-
- if ((ret = h2o_http2_decode_priority_payload(&payload, frame, err_desc)) != 0)
- return ret;
- if (frame->stream_id == payload.dependency) {
- *err_desc = "stream cannot depend on itself";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
-
- if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) != NULL) {
- stream->received_priority = payload;
- /* ignore priority changes to pushed streams with weight=257, since that is where we are trying to be smarter than the web
- * browsers
- */
- if (h2o_http2_scheduler_get_weight(&stream->_refs.scheduler) != 257)
- set_priority(conn, stream, &payload, 1);
- } else {
- if (h2o_http2_stream_is_push(frame->stream_id)) {
- /* Ignore PRIORITY frames for closed or idle pushed streams */
- return 0;
- } else {
- /* Ignore PRIORITY frames for closed pull streams */
- if (frame->stream_id <= conn->pull_stream_ids.max_open)
- return 0;
- }
- if (conn->num_streams.priority.open >= conn->super.ctx->globalconf->http2.max_streams_for_priority) {
- *err_desc = "too many streams in idle/closed state";
- /* RFC 7540 10.5: An endpoint MAY treat activity that is suspicious as a connection error (Section 5.4.1) of type
- * ENHANCE_YOUR_CALM.
- */
- return H2O_HTTP2_ERROR_ENHANCE_YOUR_CALM;
- }
- stream = h2o_http2_stream_open(conn, frame->stream_id, NULL, &payload);
- set_priority(conn, stream, &payload, 0);
- }
-
- return 0;
-}
-
-static void resume_send(h2o_http2_conn_t *conn)
-{
- if (h2o_http2_conn_get_buffer_window(conn) <= 0)
- return;
-#if 0 /* TODO reenable this check for performance? */
- if (conn->scheduler.list.size == 0)
- return;
-#endif
- request_gathered_write(conn);
-}
-
-static int handle_settings_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
-{
- if (frame->stream_id != 0) {
- *err_desc = "invalid stream id in SETTINGS frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
-
- if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) != 0) {
- if (frame->length != 0) {
- *err_desc = "invalid SETTINGS frame (+ACK)";
- return H2O_HTTP2_ERROR_FRAME_SIZE;
- }
- } else {
- uint32_t prev_initial_window_size = conn->peer_settings.initial_window_size;
- /* FIXME handle SETTINGS_HEADER_TABLE_SIZE */
- int ret = h2o_http2_update_peer_settings(&conn->peer_settings, frame->payload, frame->length, err_desc);
- if (ret != 0)
- return ret;
- { /* schedule ack */
- h2o_iovec_t header_buf = h2o_buffer_reserve(&conn->_write.buf, H2O_HTTP2_FRAME_HEADER_SIZE);
- h2o_http2_encode_frame_header((void *)header_buf.base, 0, H2O_HTTP2_FRAME_TYPE_SETTINGS, H2O_HTTP2_FRAME_FLAG_ACK, 0);
- conn->_write.buf->size += H2O_HTTP2_FRAME_HEADER_SIZE;
- h2o_http2_conn_request_write(conn);
- }
- /* apply the change to window size (to all the streams but not the connection, see 6.9.2 of draft-15) */
- if (prev_initial_window_size != conn->peer_settings.initial_window_size) {
- ssize_t delta = (int32_t)conn->peer_settings.initial_window_size - (int32_t)prev_initial_window_size;
- h2o_http2_stream_t *stream;
- kh_foreach_value(conn->streams, stream, { update_stream_output_window(stream, delta); });
- resume_send(conn);
- }
- }
-
- return 0;
-}
-
-static int handle_window_update_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
-{
- h2o_http2_window_update_payload_t payload;
- int ret, err_is_stream_level;
-
- if ((ret = h2o_http2_decode_window_update_payload(&payload, frame, err_desc, &err_is_stream_level)) != 0) {
- if (err_is_stream_level) {
- h2o_http2_stream_t *stream = h2o_http2_conn_get_stream(conn, frame->stream_id);
- if (stream != NULL)
- h2o_http2_stream_reset(conn, stream);
- stream_send_error(conn, frame->stream_id, ret);
- return 0;
- } else {
- return ret;
- }
- }
-
- if (frame->stream_id == 0) {
- if (h2o_http2_window_update(&conn->_write.window, payload.window_size_increment) != 0) {
- *err_desc = "flow control window overflow";
- return H2O_HTTP2_ERROR_FLOW_CONTROL;
- }
- } else if (!is_idle_stream_id(conn, frame->stream_id)) {
- h2o_http2_stream_t *stream = h2o_http2_conn_get_stream(conn, frame->stream_id);
- if (stream != NULL) {
- if (update_stream_output_window(stream, payload.window_size_increment) != 0) {
- h2o_http2_stream_reset(conn, stream);
- stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_FLOW_CONTROL);
- return 0;
- }
- }
- } else {
- *err_desc = "invalid stream id in WINDOW_UPDATE frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
-
- resume_send(conn);
-
- return 0;
-}
-
-static int handle_goaway_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
-{
- h2o_http2_goaway_payload_t payload;
- int ret;
-
- if ((ret = h2o_http2_decode_goaway_payload(&payload, frame, err_desc)) != 0)
- return ret;
-
- /* stop opening new push streams hereafter */
- conn->push_stream_ids.max_open = 0x7ffffffe;
-
- return 0;
-}
-
-static int handle_ping_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
-{
- h2o_http2_ping_payload_t payload;
- int ret;
-
- if ((ret = h2o_http2_decode_ping_payload(&payload, frame, err_desc)) != 0)
- return ret;
-
- if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) == 0) {
- h2o_http2_encode_ping_frame(&conn->_write.buf, 1, payload.data);
- h2o_http2_conn_request_write(conn);
- }
-
- return 0;
-}
-
-static int handle_rst_stream_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
-{
- h2o_http2_rst_stream_payload_t payload;
- h2o_http2_stream_t *stream;
- int ret;
-
- if ((ret = h2o_http2_decode_rst_stream_payload(&payload, frame, err_desc)) != 0)
- return ret;
- if (is_idle_stream_id(conn, frame->stream_id)) {
- *err_desc = "unexpected stream id in RST_STREAM frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
-
- stream = h2o_http2_conn_get_stream(conn, frame->stream_id);
- if (stream != NULL) {
- /* reset the stream */
- h2o_http2_stream_reset(conn, stream);
- }
- /* TODO log */
-
- return 0;
-}
-
-static int handle_push_promise_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
-{
- *err_desc = "received PUSH_PROMISE frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
-}
-
-static int handle_invalid_continuation_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
-{
- *err_desc = "received invalid CONTINUATION frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
-}
-
-ssize_t expect_default(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
-{
- h2o_http2_frame_t frame;
- ssize_t ret;
- static int (*FRAME_HANDLERS[])(h2o_http2_conn_t * conn, h2o_http2_frame_t * frame, const char **err_desc) = {
- handle_data_frame, /* DATA */
- handle_headers_frame, /* HEADERS */
- handle_priority_frame, /* PRIORITY */
- handle_rst_stream_frame, /* RST_STREAM */
- handle_settings_frame, /* SETTINGS */
- handle_push_promise_frame, /* PUSH_PROMISE */
- handle_ping_frame, /* PING */
- handle_goaway_frame, /* GOAWAY */
- handle_window_update_frame, /* WINDOW_UPDATE */
- handle_invalid_continuation_frame /* CONTINUATION */
- };
-
- if ((ret = h2o_http2_decode_frame(&frame, src, len, &H2O_HTTP2_SETTINGS_HOST, err_desc)) < 0)
- return ret;
-
- if (frame.type < sizeof(FRAME_HANDLERS) / sizeof(FRAME_HANDLERS[0])) {
- int hret = FRAME_HANDLERS[frame.type](conn, &frame, err_desc);
- if (hret != 0)
- ret = hret;
- } else {
- fprintf(stderr, "skipping frame (type:%d)\n", frame.type);
- }
-
- return ret;
-}
-
-static ssize_t expect_preface(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
-{
- if (len < CONNECTION_PREFACE.len) {
- return H2O_HTTP2_ERROR_INCOMPLETE;
- }
- if (memcmp(src, CONNECTION_PREFACE.base, CONNECTION_PREFACE.len) != 0) {
- return H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY;
- }
-
- { /* send SETTINGS */
- h2o_iovec_t vec = h2o_buffer_reserve(&conn->_write.buf, SETTINGS_HOST_BIN.len);
- memcpy(vec.base, SETTINGS_HOST_BIN.base, SETTINGS_HOST_BIN.len);
- conn->_write.buf->size += SETTINGS_HOST_BIN.len;
- h2o_http2_conn_request_write(conn);
- }
-
- conn->_read_expect = expect_default;
- return CONNECTION_PREFACE.len;
-}
-
-static int parse_input(h2o_http2_conn_t *conn)
-{
- /* handle the input */
- while (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING && conn->sock->input->size != 0) {
- /* process a frame */
- const char *err_desc = NULL;
- ssize_t ret = conn->_read_expect(conn, (uint8_t *)conn->sock->input->bytes, conn->sock->input->size, &err_desc);
- if (ret == H2O_HTTP2_ERROR_INCOMPLETE) {
- break;
- } else if (ret < 0) {
- if (ret != H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY) {
- enqueue_goaway(conn, (int)ret,
- err_desc != NULL ? (h2o_iovec_t){(char *)err_desc, strlen(err_desc)} : (h2o_iovec_t){NULL});
- }
- return close_connection(conn);
- }
- /* advance to the next frame */
- h2o_buffer_consume(&conn->sock->input, ret);
- }
- return 0;
-}
-
-static void on_read(h2o_socket_t *sock, const char *err)
-{
- h2o_http2_conn_t *conn = sock->data;
-
- if (err != NULL) {
- conn->super.ctx->http2.events.read_closed++;
- h2o_socket_read_stop(conn->sock);
- close_connection(conn);
- return;
- }
-
- update_idle_timeout(conn);
- if (parse_input(conn) != 0)
- return;
-
- /* write immediately, if there is no write in flight and if pending write exists */
- if (h2o_timeout_is_linked(&conn->_write.timeout_entry)) {
- h2o_timeout_unlink(&conn->_write.timeout_entry);
- do_emit_writereq(conn);
- }
-}
-
-static void on_upgrade_complete(void *_conn, h2o_socket_t *sock, size_t reqsize)
-{
- h2o_http2_conn_t *conn = _conn;
-
- if (sock == NULL) {
- close_connection(conn);
- return;
- }
-
- conn->sock = sock;
- sock->data = conn;
- conn->_http1_req_input = sock->input;
- h2o_buffer_init(&sock->input, &h2o_socket_buffer_prototype);
-
- /* setup inbound */
- h2o_socket_read_start(conn->sock, on_read);
-
- /* handle the request */
- execute_or_enqueue_request(conn, h2o_http2_conn_get_stream(conn, 1));
-
- if (conn->_http1_req_input->size > reqsize) {
- size_t remaining_bytes = conn->_http1_req_input->size - reqsize;
- h2o_buffer_reserve(&sock->input, remaining_bytes);
- memcpy(sock->input->bytes, conn->_http1_req_input->bytes + reqsize, remaining_bytes);
- sock->input->size += remaining_bytes;
- on_read(conn->sock, NULL);
- }
-}
-
-static size_t bytes_in_buf(h2o_http2_conn_t *conn)
-{
- size_t size = conn->_write.buf->size;
- if (conn->_write.buf_in_flight != 0)
- size += conn->_write.buf_in_flight->size;
- return size;
-}
-
-void h2o_http2_conn_request_write(h2o_http2_conn_t *conn)
-{
- if (conn->state == H2O_HTTP2_CONN_STATE_IS_CLOSING)
- return;
- if (h2o_socket_is_reading(conn->sock) && bytes_in_buf(conn) >= H2O_HTTP2_DEFAULT_OUTBUF_SOFT_MAX_SIZE)
- h2o_socket_read_stop(conn->sock);
- request_gathered_write(conn);
-}
-
-void h2o_http2_conn_register_for_proceed_callback(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- h2o_http2_conn_request_write(conn);
-
- if (h2o_http2_stream_has_pending_data(stream) || stream->state >= H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL) {
- if (h2o_http2_window_get_window(&stream->output_window) > 0) {
- assert(!h2o_linklist_is_linked(&stream->_refs.link));
- h2o_http2_scheduler_activate(&stream->_refs.scheduler);
- }
- } else {
- h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_refs.link);
- }
-}
-
-static void on_notify_write(h2o_socket_t *sock, const char *err)
-{
- h2o_http2_conn_t *conn = sock->data;
-
- if (err != NULL) {
- close_connection_now(conn);
- return;
- }
- do_emit_writereq(conn);
-}
-
-static void on_write_complete(h2o_socket_t *sock, const char *err)
-{
- h2o_http2_conn_t *conn = sock->data;
-
- assert(conn->_write.buf_in_flight != NULL);
-
- /* close by error if necessary */
- if (err != NULL) {
- conn->super.ctx->http2.events.write_closed++;
- close_connection_now(conn);
- return;
- }
-
- /* reset the other memory pool */
- h2o_buffer_dispose(&conn->_write.buf_in_flight);
- assert(conn->_write.buf_in_flight == NULL);
-
- /* call the proceed callback of the streams that have been flushed (while unlinking them from the list) */
- if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
- while (!h2o_linklist_is_empty(&conn->_write.streams_to_proceed)) {
- h2o_http2_stream_t *stream =
- H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _refs.link, conn->_write.streams_to_proceed.next);
- assert(!h2o_http2_stream_has_pending_data(stream));
- h2o_linklist_unlink(&stream->_refs.link);
- h2o_http2_stream_proceed(conn, stream);
- }
- }
-
- /* cancel the write callback if scheduled (as the generator may have scheduled a write just before this function gets called) */
- if (h2o_timeout_is_linked(&conn->_write.timeout_entry))
- h2o_timeout_unlink(&conn->_write.timeout_entry);
-
- if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
- if (!h2o_socket_is_reading(conn->sock) && bytes_in_buf(conn) < H2O_HTTP2_DEFAULT_OUTBUF_SOFT_MAX_SIZE)
- h2o_socket_read_start(conn->sock, on_read);
- }
-
-#if !H2O_USE_LIBUV
- if (conn->state == H2O_HTTP2_CONN_STATE_OPEN) {
- if (conn->_write.buf->size != 0 || h2o_http2_scheduler_is_active(&conn->scheduler))
- h2o_socket_notify_write(sock, on_notify_write);
- return;
- }
-#endif
-
- /* write more, if possible */
- do_emit_writereq(conn);
-}
-
-static int emit_writereq_of_openref(h2o_http2_scheduler_openref_t *ref, int *still_is_active, void *cb_arg)
-{
- h2o_http2_conn_t *conn = cb_arg;
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _refs.scheduler, ref);
-
- assert(h2o_http2_stream_has_pending_data(stream) || stream->state >= H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL);
-
- *still_is_active = 0;
-
- h2o_http2_stream_send_pending_data(conn, stream);
- if (h2o_http2_stream_has_pending_data(stream) || stream->state == H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL) {
- if (h2o_http2_window_get_window(&stream->output_window) <= 0) {
- /* is blocked */
- } else {
- *still_is_active = 1;
- }
- } else {
- h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_refs.link);
- }
-
- return h2o_http2_conn_get_buffer_window(conn) > 0 ? 0 : -1;
-}
-
-void do_emit_writereq(h2o_http2_conn_t *conn)
-{
- assert(conn->_write.buf_in_flight == NULL);
-
- /* push DATA frames */
- if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING && h2o_http2_conn_get_buffer_window(conn) > 0)
- h2o_http2_scheduler_run(&conn->scheduler, emit_writereq_of_openref, conn);
-
- if (conn->_write.buf->size != 0) {
- /* write and wait for completion */
- h2o_iovec_t buf = {conn->_write.buf->bytes, conn->_write.buf->size};
- h2o_socket_write(conn->sock, &buf, 1, on_write_complete);
- conn->_write.buf_in_flight = conn->_write.buf;
- h2o_buffer_init(&conn->_write.buf, &wbuf_buffer_prototype);
- }
-
- /* close the connection if necessary */
- switch (conn->state) {
- case H2O_HTTP2_CONN_STATE_OPEN:
- break;
- case H2O_HTTP2_CONN_STATE_HALF_CLOSED:
- if (conn->num_streams.pull.half_closed + conn->num_streams.push.half_closed != 0)
- break;
- conn->state = H2O_HTTP2_CONN_STATE_IS_CLOSING;
- /* fall-thru */
- case H2O_HTTP2_CONN_STATE_IS_CLOSING:
- close_connection_now(conn);
- break;
- }
-}
-
-static void emit_writereq(h2o_timeout_entry_t *entry)
-{
- h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _write.timeout_entry, entry);
-
- do_emit_writereq(conn);
-}
-
-static socklen_t get_sockname(h2o_conn_t *_conn, struct sockaddr *sa)
-{
- h2o_http2_conn_t *conn = (void *)_conn;
- return h2o_socket_getsockname(conn->sock, sa);
-}
-
-static socklen_t get_peername(h2o_conn_t *_conn, struct sockaddr *sa)
-{
- h2o_http2_conn_t *conn = (void *)_conn;
- return h2o_socket_getpeername(conn->sock, sa);
-}
-
-static h2o_socket_t *get_socket(h2o_conn_t *_conn)
-{
- h2o_http2_conn_t *conn = (void *)_conn;
- return conn->sock;
-}
-
-#define DEFINE_TLS_LOGGER(name) \
- static h2o_iovec_t log_##name(h2o_req_t *req) \
- { \
- h2o_http2_conn_t *conn = (void *)req->conn; \
- return h2o_socket_log_ssl_##name(conn->sock, &req->pool); \
- }
-
-DEFINE_TLS_LOGGER(protocol_version)
-DEFINE_TLS_LOGGER(session_reused)
-DEFINE_TLS_LOGGER(cipher)
-DEFINE_TLS_LOGGER(cipher_bits)
-DEFINE_TLS_LOGGER(session_id)
-#undef DEFINE_TLS_LOGGER
-
-static h2o_iovec_t log_stream_id(h2o_req_t *req)
-{
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
- char *s = h2o_mem_alloc_pool(&stream->req.pool, sizeof(H2O_UINT32_LONGEST_STR));
- size_t len = (size_t)sprintf(s, "%" PRIu32, stream->stream_id);
- return h2o_iovec_init(s, len);
-}
-
-static h2o_iovec_t log_priority_received(h2o_req_t *req)
-{
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
- char *s = h2o_mem_alloc_pool(&stream->req.pool, sizeof("1:" H2O_UINT32_LONGEST_STR ":" H2O_UINT16_LONGEST_STR));
- size_t len = (size_t)sprintf(s, "%c:%" PRIu32 ":%" PRIu16, stream->received_priority.exclusive ? '1' : '0',
- stream->received_priority.dependency, stream->received_priority.weight);
- return h2o_iovec_init(s, len);
-}
-
-static h2o_iovec_t log_priority_received_exclusive(h2o_req_t *req)
-{
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
- return h2o_iovec_init(stream->received_priority.exclusive ? "1" : "0", 1);
-}
-
-static h2o_iovec_t log_priority_received_parent(h2o_req_t *req)
-{
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
- char *s = h2o_mem_alloc_pool(&stream->req.pool, sizeof(H2O_UINT32_LONGEST_STR));
- size_t len = sprintf(s, "%" PRIu32, stream->received_priority.dependency);
- return h2o_iovec_init(s, len);
-}
-
-static h2o_iovec_t log_priority_received_weight(h2o_req_t *req)
-{
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
- char *s = h2o_mem_alloc_pool(&stream->req.pool, sizeof(H2O_UINT16_LONGEST_STR));
- size_t len = sprintf(s, "%" PRIu16, stream->received_priority.weight);
- return h2o_iovec_init(s, len);
-}
-
-static uint32_t get_parent_stream_id(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- h2o_http2_scheduler_node_t *parent_sched = h2o_http2_scheduler_get_parent(&stream->_refs.scheduler);
- if (parent_sched == &conn->scheduler) {
- return 0;
- } else {
- h2o_http2_stream_t *parent_stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _refs.scheduler, parent_sched);
- return parent_stream->stream_id;
- }
-}
-
-static h2o_iovec_t log_priority_actual(h2o_req_t *req)
-{
- h2o_http2_conn_t *conn = (void *)req->conn;
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
- char *s = h2o_mem_alloc_pool(&stream->req.pool, sizeof(H2O_UINT32_LONGEST_STR ":" H2O_UINT16_LONGEST_STR));
- size_t len = (size_t)sprintf(s, "%" PRIu32 ":%" PRIu16, get_parent_stream_id(conn, stream),
- h2o_http2_scheduler_get_weight(&stream->_refs.scheduler));
- return h2o_iovec_init(s, len);
-}
-
-static h2o_iovec_t log_priority_actual_parent(h2o_req_t *req)
-{
- h2o_http2_conn_t *conn = (void *)req->conn;
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
- char *s = h2o_mem_alloc_pool(&stream->req.pool, sizeof(H2O_UINT32_LONGEST_STR));
- size_t len = (size_t)sprintf(s, "%" PRIu32, get_parent_stream_id(conn, stream));
- return h2o_iovec_init(s, len);
-}
-
-static h2o_iovec_t log_priority_actual_weight(h2o_req_t *req)
-{
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
- char *s = h2o_mem_alloc_pool(&stream->req.pool, sizeof(H2O_UINT16_LONGEST_STR));
- size_t len = (size_t)sprintf(s, "%" PRIu16, h2o_http2_scheduler_get_weight(&stream->_refs.scheduler));
- return h2o_iovec_init(s, len);
-}
-
-static h2o_http2_conn_t *create_conn(h2o_context_t *ctx, h2o_hostconf_t **hosts, h2o_socket_t *sock, struct timeval connected_at)
-{
- static const h2o_conn_callbacks_t callbacks = {
- get_sockname, /* stringify address */
- get_peername, /* ditto */
- push_path, /* HTTP2 push */
- get_socket, /* get underlying socket */
- h2o_http2_get_debug_state, /* get debug state */
- {{
- {log_protocol_version, log_session_reused, log_cipher, log_cipher_bits, log_session_id}, /* ssl */
- {NULL}, /* http1 */
- {log_stream_id, log_priority_received, log_priority_received_exclusive, log_priority_received_parent,
- log_priority_received_weight, log_priority_actual, log_priority_actual_parent, log_priority_actual_weight} /* http2 */
- }} /* loggers */
- };
-
- h2o_http2_conn_t *conn = (void *)h2o_create_connection(sizeof(*conn), ctx, hosts, connected_at, &callbacks);
-
- memset((char *)conn + sizeof(conn->super), 0, sizeof(*conn) - sizeof(conn->super));
- conn->sock = sock;
- conn->peer_settings = H2O_HTTP2_SETTINGS_DEFAULT;
- conn->streams = kh_init(h2o_http2_stream_t);
- h2o_http2_scheduler_init(&conn->scheduler);
- conn->state = H2O_HTTP2_CONN_STATE_OPEN;
- h2o_linklist_insert(&ctx->http2._conns, &conn->_conns);
- conn->_read_expect = expect_preface;
- conn->_input_header_table.hpack_capacity = conn->_input_header_table.hpack_max_capacity =
- H2O_HTTP2_SETTINGS_DEFAULT.header_table_size;
- h2o_http2_window_init(&conn->_input_window, &H2O_HTTP2_SETTINGS_DEFAULT);
- conn->_output_header_table.hpack_capacity = H2O_HTTP2_SETTINGS_HOST.header_table_size;
- h2o_linklist_init_anchor(&conn->_pending_reqs);
- h2o_buffer_init(&conn->_write.buf, &wbuf_buffer_prototype);
- h2o_linklist_init_anchor(&conn->_write.streams_to_proceed);
- conn->_write.timeout_entry.cb = emit_writereq;
- h2o_http2_window_init(&conn->_write.window, &conn->peer_settings);
-
- return conn;
-}
-
-static int update_push_memo(h2o_http2_conn_t *conn, h2o_req_t *src_req, const char *abspath, size_t abspath_len)
-{
-
- if (conn->push_memo == NULL)
- conn->push_memo = h2o_cache_create(0, 1024, 1, NULL);
-
- /* uses the hash as the key */
- h2o_cache_hashcode_t url_hash = h2o_cache_calchash(src_req->input.scheme->name.base, src_req->input.scheme->name.len) ^
- h2o_cache_calchash(src_req->input.authority.base, src_req->input.authority.len) ^
- h2o_cache_calchash(abspath, abspath_len);
- return h2o_cache_set(conn->push_memo, 0, h2o_iovec_init(&url_hash, sizeof(url_hash)), url_hash, h2o_iovec_init(NULL, 0));
-}
-
-static void push_path(h2o_req_t *src_req, const char *abspath, size_t abspath_len)
-{
- h2o_http2_conn_t *conn = (void *)src_req->conn;
- h2o_http2_stream_t *src_stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, src_req);
-
- /* RFC 7540 8.2.1: PUSH_PROMISE frames can be sent by the server in response to any client-initiated stream */
- if (h2o_http2_stream_is_push(src_stream->stream_id))
- return;
-
- if (!src_stream->req.hostconf->http2.push_preload || !conn->peer_settings.enable_push ||
- conn->num_streams.push.open >= conn->peer_settings.max_concurrent_streams)
- return;
-
- if (conn->push_stream_ids.max_open >= 0x7ffffff0)
- return;
- if (!(h2o_linklist_is_empty(&conn->_pending_reqs) && can_run_requests(conn)))
- return;
-
- if (h2o_find_header(&src_stream->req.headers, H2O_TOKEN_X_FORWARDED_FOR, -1) != -1)
- return;
-
- if (src_stream->cache_digests != NULL) {
- h2o_iovec_t url = h2o_concat(&src_stream->req.pool, src_stream->req.input.scheme->name, h2o_iovec_init(H2O_STRLIT("://")),
- src_stream->req.input.authority, h2o_iovec_init(abspath, abspath_len));
- if (h2o_cache_digests_lookup_by_url(src_stream->cache_digests, url.base, url.len) == H2O_CACHE_DIGESTS_STATE_FRESH)
- return;
- }
-
- /* delayed initialization of casper (cookie-based), that MAY be used together to cache-digests */
- if (src_stream->req.hostconf->http2.casper.capacity_bits != 0) {
- if (!src_stream->pull.casper_is_ready) {
- src_stream->pull.casper_is_ready = 1;
- if (conn->casper == NULL)
- h2o_http2_conn_init_casper(conn, src_stream->req.hostconf->http2.casper.capacity_bits);
- ssize_t header_index;
- for (header_index = -1;
- (header_index = h2o_find_header(&src_stream->req.headers, H2O_TOKEN_COOKIE, header_index)) != -1;) {
- h2o_header_t *header = src_stream->req.headers.entries + header_index;
- h2o_http2_casper_consume_cookie(conn->casper, header->value.base, header->value.len);
- }
- }
- }
-
- /* update the push memo, and if it already pushed on the same connection, return */
- if (update_push_memo(conn, &src_stream->req, abspath, abspath_len))
- return;
-
- /* open the stream */
- h2o_http2_stream_t *stream = h2o_http2_stream_open(conn, conn->push_stream_ids.max_open + 2, NULL, &h2o_http2_default_priority);
- stream->received_priority.dependency = src_stream->stream_id;
- stream->push.parent_stream_id = src_stream->stream_id;
- h2o_http2_scheduler_open(&stream->_refs.scheduler, &src_stream->_refs.scheduler.node, 16, 0);
- h2o_http2_stream_prepare_for_request(conn, stream);
-
- /* setup request */
- stream->req.input.method = (h2o_iovec_t){H2O_STRLIT("GET")};
- stream->req.input.scheme = src_stream->req.input.scheme;
- stream->req.input.authority =
- h2o_strdup(&stream->req.pool, src_stream->req.input.authority.base, src_stream->req.input.authority.len);
- stream->req.input.path = h2o_strdup(&stream->req.pool, abspath, abspath_len);
- stream->req.version = 0x200;
-
- { /* copy headers that may affect the response (of a cacheable response) */
- size_t i;
- for (i = 0; i != src_stream->req.headers.size; ++i) {
- h2o_header_t *src_header = src_stream->req.headers.entries + i;
- if (h2o_iovec_is_token(src_header->name)) {
- h2o_token_t *token = H2O_STRUCT_FROM_MEMBER(h2o_token_t, buf, src_header->name);
- if (token->copy_for_push_request) {
- h2o_add_header(&stream->req.pool, &stream->req.headers, token, NULL,
- h2o_strdup(&stream->req.pool, src_header->value.base, src_header->value.len).base,
- src_header->value.len);
- }
- }
- }
- }
-
- execute_or_enqueue_request(conn, stream);
-
- /* send push-promise ASAP (before the parent stream gets closed), even if execute_or_enqueue_request did not trigger the
- * invocation of send_headers */
- if (!stream->push.promise_sent && stream->state != H2O_HTTP2_STREAM_STATE_END_STREAM)
- h2o_http2_stream_send_push_promise(conn, stream);
-}
-
-static int foreach_request(h2o_context_t *ctx, int (*cb)(h2o_req_t *req, void *cbdata), void *cbdata)
-{
- h2o_linklist_t *node;
-
- for (node = ctx->http2._conns.next; node != &ctx->http2._conns; node = node->next) {
- h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _conns, node);
- h2o_http2_stream_t *stream;
- kh_foreach_value(conn->streams, stream, {
- int ret = cb(&stream->req, cbdata);
- if (ret != 0)
- return ret;
- });
- }
- return 0;
-}
-
-void h2o_http2_accept(h2o_accept_ctx_t *ctx, h2o_socket_t *sock, struct timeval connected_at)
-{
- h2o_http2_conn_t *conn = create_conn(ctx->ctx, ctx->hosts, sock, connected_at);
- sock->data = conn;
- h2o_socket_read_start(conn->sock, on_read);
- update_idle_timeout(conn);
- if (sock->input->size != 0)
- on_read(sock, 0);
-}
-
-int h2o_http2_handle_upgrade(h2o_req_t *req, struct timeval connected_at)
-{
- h2o_http2_conn_t *http2conn = create_conn(req->conn->ctx, req->conn->hosts, NULL, connected_at);
- h2o_http2_stream_t *stream;
- ssize_t connection_index, settings_index;
- h2o_iovec_t settings_decoded;
- const char *err_desc;
-
- assert(req->version < 0x200); /* from HTTP/1.x */
-
- /* check that "HTTP2-Settings" is declared in the connection header */
- connection_index = h2o_find_header(&req->headers, H2O_TOKEN_CONNECTION, -1);
- assert(connection_index != -1);
- if (!h2o_contains_token(req->headers.entries[connection_index].value.base, req->headers.entries[connection_index].value.len,
- H2O_STRLIT("http2-settings"), ',')) {
- goto Error;
- }
-
- /* decode the settings */
- if ((settings_index = h2o_find_header(&req->headers, H2O_TOKEN_HTTP2_SETTINGS, -1)) == -1) {
- goto Error;
- }
- if ((settings_decoded = h2o_decode_base64url(&req->pool, req->headers.entries[settings_index].value.base,
- req->headers.entries[settings_index].value.len))
- .base == NULL) {
- goto Error;
- }
- if (h2o_http2_update_peer_settings(&http2conn->peer_settings, (uint8_t *)settings_decoded.base, settings_decoded.len,
- &err_desc) != 0) {
- goto Error;
- }
-
- /* open the stream, now that the function is guaranteed to succeed */
- stream = h2o_http2_stream_open(http2conn, 1, req, &h2o_http2_default_priority);
- h2o_http2_scheduler_open(&stream->_refs.scheduler, &http2conn->scheduler, h2o_http2_default_priority.weight, 0);
- h2o_http2_stream_prepare_for_request(http2conn, stream);
-
- /* send response */
- req->res.status = 101;
- req->res.reason = "Switching Protocols";
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_UPGRADE, NULL, H2O_STRLIT("h2c"));
- h2o_http1_upgrade(req, (h2o_iovec_t *)&SETTINGS_HOST_BIN, 1, on_upgrade_complete, http2conn);
-
- return 0;
-Error:
- h2o_linklist_unlink(&http2conn->_conns);
- kh_destroy(h2o_http2_stream_t, http2conn->streams);
- free(http2conn);
- return -1;
-}
diff --git a/web/server/h2o/libh2o/lib/http2/frame.c b/web/server/h2o/libh2o/lib/http2/frame.c
deleted file mode 100644
index 86abdaa48..000000000
--- a/web/server/h2o/libh2o/lib/http2/frame.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * 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 "h2o.h"
-#include "h2o/http2.h"
-#include "h2o/http2_internal.h"
-
-const h2o_http2_settings_t H2O_HTTP2_SETTINGS_DEFAULT = {
- /* header_table_size */ 4096,
- /* enable_push */ 1,
- /* max_concurrent_streams */ UINT32_MAX,
- /* initial_window_size */ 65535,
- /* max_frame_size */ 16384};
-
-int h2o_http2_update_peer_settings(h2o_http2_settings_t *settings, const uint8_t *src, size_t len, const char **err_desc)
-{
- for (; len >= 6; len -= 6, src += 6) {
- uint16_t identifier = h2o_http2_decode16u(src);
- uint32_t value = h2o_http2_decode32u(src + 2);
- switch (identifier) {
-#define SET(label, member, min, max, err_code) \
- case H2O_HTTP2_SETTINGS_##label: \
- if (!(min <= value && value <= max)) { \
- *err_desc = "invalid SETTINGS frame"; \
- return err_code; \
- } \
- settings->member = value; \
- break
- SET(HEADER_TABLE_SIZE, header_table_size, 0, UINT32_MAX, 0);
- SET(ENABLE_PUSH, enable_push, 0, 1, H2O_HTTP2_ERROR_PROTOCOL);
- SET(MAX_CONCURRENT_STREAMS, max_concurrent_streams, 0, UINT32_MAX, 0);
- SET(INITIAL_WINDOW_SIZE, initial_window_size, 0, 0x7fffffff, H2O_HTTP2_ERROR_FLOW_CONTROL);
- SET(MAX_FRAME_SIZE, max_frame_size, 16384, 16777215, H2O_HTTP2_ERROR_PROTOCOL);
-#undef SET
- default:
- /* ignore unknown (5.5) */
- break;
- }
- }
-
- if (len != 0)
- return H2O_HTTP2_ERROR_FRAME_SIZE;
- return 0;
-}
-
-uint8_t *h2o_http2_encode_frame_header(uint8_t *dst, size_t length, uint8_t type, uint8_t flags, int32_t stream_id)
-{
- if (length > 0xffffff)
- h2o_fatal("invalid length");
-
- dst = h2o_http2_encode24u(dst, (uint32_t)length);
- *dst++ = type;
- *dst++ = flags;
- dst = h2o_http2_encode32u(dst, stream_id);
-
- return dst;
-}
-
-static uint8_t *allocate_frame(h2o_buffer_t **buf, size_t length, uint8_t type, uint8_t flags, int32_t stream_id)
-{
- h2o_iovec_t alloced = h2o_buffer_reserve(buf, H2O_HTTP2_FRAME_HEADER_SIZE + length);
- (*buf)->size += H2O_HTTP2_FRAME_HEADER_SIZE + length;
- return h2o_http2_encode_frame_header((uint8_t *)alloced.base, length, type, flags, stream_id);
-}
-
-void h2o_http2__encode_rst_stream_frame(h2o_buffer_t **buf, uint32_t stream_id, int errnum)
-{
- uint8_t *dst = allocate_frame(buf, 4, H2O_HTTP2_FRAME_TYPE_RST_STREAM, 0, stream_id);
- dst = h2o_http2_encode32u(dst, errnum);
-}
-
-void h2o_http2_encode_ping_frame(h2o_buffer_t **buf, int is_ack, const uint8_t *data)
-{
- uint8_t *dst = allocate_frame(buf, 8, H2O_HTTP2_FRAME_TYPE_PING, is_ack ? H2O_HTTP2_FRAME_FLAG_ACK : 0, 0);
- memcpy(dst, data, 8);
- dst += 8;
-}
-
-void h2o_http2_encode_goaway_frame(h2o_buffer_t **buf, uint32_t last_stream_id, int errnum, h2o_iovec_t additional_data)
-{
- uint8_t *dst = allocate_frame(buf, 8 + additional_data.len, H2O_HTTP2_FRAME_TYPE_GOAWAY, 0, 0);
- dst = h2o_http2_encode32u(dst, last_stream_id);
- dst = h2o_http2_encode32u(dst, (uint32_t)-errnum);
- h2o_memcpy(dst, additional_data.base, additional_data.len);
-}
-
-void h2o_http2_encode_window_update_frame(h2o_buffer_t **buf, uint32_t stream_id, int32_t window_size_increment)
-{
- uint8_t *dst = allocate_frame(buf, 4, H2O_HTTP2_FRAME_TYPE_WINDOW_UPDATE, 0, stream_id);
- dst = h2o_http2_encode32u(dst, window_size_increment);
-}
-
-ssize_t h2o_http2_decode_frame(h2o_http2_frame_t *frame, const uint8_t *src, size_t len, const h2o_http2_settings_t *host_settings,
- const char **err_desc)
-{
- if (len < H2O_HTTP2_FRAME_HEADER_SIZE)
- return H2O_HTTP2_ERROR_INCOMPLETE;
-
- frame->length = h2o_http2_decode24u(src);
- frame->type = src[3];
- frame->flags = src[4];
- frame->stream_id = h2o_http2_decode32u(src + 5) & 0x7fffffff;
-
- if (frame->length > host_settings->max_frame_size)
- return H2O_HTTP2_ERROR_FRAME_SIZE;
-
- if (len < H2O_HTTP2_FRAME_HEADER_SIZE + frame->length)
- return H2O_HTTP2_ERROR_INCOMPLETE;
-
- frame->payload = src + H2O_HTTP2_FRAME_HEADER_SIZE;
-
- return H2O_HTTP2_FRAME_HEADER_SIZE + frame->length;
-}
-
-int h2o_http2_decode_data_payload(h2o_http2_data_payload_t *payload, const h2o_http2_frame_t *frame, const char **err_desc)
-{
- if (frame->stream_id == 0) {
- *err_desc = "invalid stream id in DATA frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
-
- if ((frame->flags & H2O_HTTP2_FRAME_FLAG_PADDED) != 0) {
- uint8_t padding_length;
- if (frame->length < 1) {
- *err_desc = "invalid DATA frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- padding_length = frame->payload[0];
- if (frame->length < 1 + padding_length) {
- *err_desc = "invalid DATA frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- payload->data = frame->payload + 1;
- payload->length = frame->length - (1 + padding_length);
- } else {
- payload->data = frame->payload;
- payload->length = frame->length;
- }
- return 0;
-}
-
-static const uint8_t *decode_priority(h2o_http2_priority_t *priority, const uint8_t *src)
-{
- uint32_t u4 = h2o_http2_decode32u(src);
- src += 4;
- priority->exclusive = u4 >> 31;
- priority->dependency = u4 & 0x7fffffff;
- priority->weight = (uint16_t)*src++ + 1;
- return src;
-}
-
-int h2o_http2_decode_headers_payload(h2o_http2_headers_payload_t *payload, const h2o_http2_frame_t *frame, const char **err_desc)
-{
- const uint8_t *src = frame->payload, *src_end = frame->payload + frame->length;
-
- if (frame->stream_id == 0) {
- *err_desc = "invalid stream id in HEADERS frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
-
- if ((frame->flags & H2O_HTTP2_FRAME_FLAG_PADDED) != 0) {
- uint32_t padlen;
- if (src == src_end) {
- *err_desc = "invalid HEADERS frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- padlen = *src++;
- if (src_end - src < padlen) {
- *err_desc = "invalid HEADERS frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- src_end -= padlen;
- }
-
- if ((frame->flags & H2O_HTTP2_FRAME_FLAG_PRIORITY) != 0) {
- if (src_end - src < 5)
- return -1;
- src = decode_priority(&payload->priority, src);
- } else {
- payload->priority = h2o_http2_default_priority;
- }
-
- payload->headers = src;
- payload->headers_len = src_end - src;
-
- return 0;
-}
-
-int h2o_http2_decode_priority_payload(h2o_http2_priority_t *payload, const h2o_http2_frame_t *frame, const char **err_desc)
-{
- if (frame->stream_id == 0) {
- *err_desc = "invalid stream id in PRIORITY frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- if (frame->length != 5) {
- *err_desc = "invalid PRIORITY frame";
- return H2O_HTTP2_ERROR_FRAME_SIZE;
- }
-
- decode_priority(payload, frame->payload);
- return 0;
-}
-
-int h2o_http2_decode_rst_stream_payload(h2o_http2_rst_stream_payload_t *payload, const h2o_http2_frame_t *frame,
- const char **err_desc)
-{
- if (frame->stream_id == 0) {
- *err_desc = "invalid stream id in RST_STREAM frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- if (frame->length != sizeof(payload->error_code)) {
- *err_desc = "invalid RST_STREAM frame";
- return H2O_HTTP2_ERROR_FRAME_SIZE;
- }
-
- payload->error_code = h2o_http2_decode32u(frame->payload);
- return 0;
-}
-
-int h2o_http2_decode_ping_payload(h2o_http2_ping_payload_t *payload, const h2o_http2_frame_t *frame, const char **err_desc)
-{
- if (frame->stream_id != 0) {
- *err_desc = "invalid PING frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- if (frame->length != sizeof(payload->data)) {
- *err_desc = "invalid PING frame";
- return H2O_HTTP2_ERROR_FRAME_SIZE;
- }
-
- memcpy(payload->data, frame->payload, sizeof(payload->data));
- return 0;
-}
-
-int h2o_http2_decode_goaway_payload(h2o_http2_goaway_payload_t *payload, const h2o_http2_frame_t *frame, const char **err_desc)
-{
- if (frame->stream_id != 0) {
- *err_desc = "invalid stream id in GOAWAY frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- if (frame->length < 8) {
- *err_desc = "invalid GOAWAY frame";
- return H2O_HTTP2_ERROR_FRAME_SIZE;
- }
-
- payload->last_stream_id = h2o_http2_decode32u(frame->payload) & 0x7fffffff;
- payload->error_code = h2o_http2_decode32u(frame->payload + 4);
- if ((payload->debug_data.len = frame->length - 8) != 0)
- payload->debug_data.base = (char *)frame->payload + 8;
- else
- payload->debug_data.base = NULL;
-
- return 0;
-}
-
-int h2o_http2_decode_window_update_payload(h2o_http2_window_update_payload_t *payload, const h2o_http2_frame_t *frame,
- const char **err_desc, int *err_is_stream_level)
-{
- if (frame->length != 4) {
- *err_is_stream_level = 0;
- return H2O_HTTP2_ERROR_FRAME_SIZE;
- }
-
- payload->window_size_increment = h2o_http2_decode32u(frame->payload) & 0x7fffffff;
- if (payload->window_size_increment == 0) {
- *err_is_stream_level = frame->stream_id != 0;
- *err_desc = "invalid WINDOW_UPDATE frame";
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
-
- return 0;
-}
diff --git a/web/server/h2o/libh2o/lib/http2/hpack.c b/web/server/h2o/libh2o/lib/http2/hpack.c
deleted file mode 100644
index 4adb15cd7..000000000
--- a/web/server/h2o/libh2o/lib/http2/hpack.c
+++ /dev/null
@@ -1,917 +0,0 @@
-/*
- * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Fastly, Inc.
- *
- * 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 <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "h2o.h"
-#include "h2o/http2.h"
-#include "h2o/http2_internal.h"
-
-#define HEADER_TABLE_OFFSET 62
-#define HEADER_TABLE_ENTRY_SIZE_OFFSET 32
-#define STATUS_HEADER_MAX_SIZE 5
-#define CONTENT_LENGTH_HEADER_MAX_SIZE \
- (3 + sizeof(H2O_UINT64_LONGEST_STR) - 1) /* uses Literal Header Field without Indexing (RFC7541 6.2.2) */
-
-struct st_h2o_hpack_static_table_entry_t {
- const h2o_token_t *name;
- const h2o_iovec_t value;
-};
-
-struct st_h2o_decode_header_result_t {
- h2o_iovec_t *name;
- h2o_iovec_t *value;
-};
-
-#include "hpack_huffman_table.h"
-#include "hpack_static_table.h"
-
-static inline int value_is_part_of_static_table(const h2o_iovec_t *value)
-{
- return &h2o_hpack_static_table[0].value <= value &&
- value <= &h2o_hpack_static_table[sizeof(h2o_hpack_static_table) / sizeof(h2o_hpack_static_table[0]) - 1].value;
-}
-
-static h2o_iovec_t *alloc_buf(h2o_mem_pool_t *pool, size_t len)
-{
- h2o_iovec_t *buf = h2o_mem_alloc_shared(pool, sizeof(h2o_iovec_t) + len + 1, NULL);
- buf->base = (char *)buf + sizeof(h2o_iovec_t);
- buf->len = len;
- return buf;
-}
-
-/* validate a header value against https://tools.ietf.org/html/rfc7230#section-3.2 */
-static int contains_invalid_field_value_char(const char *s, size_t len)
-{
- /* all printable chars + horizontal tab */
- static const char valid_h2_field_value_char[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-31 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 32-63 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 64-95 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 96-127 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 128-159 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 160-191 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 192-223 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 224-255 */
- };
-
- for (; len != 0; ++s, --len) {
- unsigned char ch = (unsigned char)*s;
- if (!valid_h2_field_value_char[ch]) {
- return 1;
- }
- }
- return 0;
-}
-
-static const char *err_found_upper_case_in_header_name = "found an upper-case letter in header name";
-static const char *soft_err_found_invalid_char_in_header_name = "found an invalid character in header name";
-static const char *soft_err_found_invalid_char_in_header_value = "found an invalid character in header value";
-
-/* validate a header name against https://tools.ietf.org/html/rfc7230#section-3.2,
- * in addition to that, we disallow upper case chars as well.
- * This sets @err_desc for all invalid characters, but only returns true
- * for upper case characters, this is because we return a protocol error
- * in that case. */
-static const char *validate_header_name(const char *s, size_t len)
-{
- const char *ret = NULL;
- /* all printable chars, except upper case and separator characters */
- static const char valid_h2_header_name_char[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-31 */
- 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 32-63 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, /* 64-95 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, /* 96-127 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-159 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 160-191 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192-223 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 224-255 */
- };
-
- for (; len != 0; ++s, --len) {
- unsigned char ch = (unsigned char)*s;
- if (!valid_h2_header_name_char[ch]) {
- if (ch - 'A' < 26U) {
- return err_found_upper_case_in_header_name;
- }
- ret = soft_err_found_invalid_char_in_header_name;
- }
- }
- return ret;
-}
-
-static int32_t decode_int(const uint8_t **src, const uint8_t *src_end, size_t prefix_bits)
-{
- int32_t value, mult;
- uint8_t prefix_max = (1 << prefix_bits) - 1;
-
- if (*src >= src_end)
- return -1;
-
- value = (uint8_t) * (*src)++ & prefix_max;
- if (value != prefix_max) {
- return value;
- }
-
- /* we only allow at most 4 octets (excluding prefix) to be used as int (== 2**(4*7) == 2**28) */
- if (src_end - *src > 4)
- src_end = *src + 4;
-
- value = prefix_max;
- for (mult = 1;; mult *= 128) {
- if (*src >= src_end)
- return -1;
- value += (**src & 127) * mult;
- if ((*(*src)++ & 128) == 0)
- return value;
- }
-}
-
-static char *huffdecode4(char *dst, uint8_t in, uint8_t *state, int *maybe_eos, uint8_t *seen_char_types)
-{
- const nghttp2_huff_decode *entry = huff_decode_table[*state] + in;
-
- if ((entry->flags & NGHTTP2_HUFF_FAIL) != 0)
- return NULL;
- if ((entry->flags & NGHTTP2_HUFF_SYM) != 0) {
- *dst++ = entry->sym;
- *seen_char_types |= (entry->flags & NGHTTP2_HUFF_INVALID_CHARS);
- }
- *state = entry->state;
- *maybe_eos = (entry->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
-
- return dst;
-}
-
-static h2o_iovec_t *decode_huffman(h2o_mem_pool_t *pool, const uint8_t *src, size_t len, uint8_t *seen_char_types)
-{
- const uint8_t *src_end = src + len;
- char *dst;
- uint8_t state = 0;
- int maybe_eos = 1;
- h2o_iovec_t *dst_buf = alloc_buf(pool, len * 2); /* max compression ratio is >= 0.5 */
-
- dst = dst_buf->base;
- for (; src < src_end; src++) {
- if ((dst = huffdecode4(dst, *src >> 4, &state, &maybe_eos, seen_char_types)) == NULL)
- return NULL;
- if ((dst = huffdecode4(dst, *src & 0xf, &state, &maybe_eos, seen_char_types)) == NULL)
- return NULL;
- }
-
- if (!maybe_eos)
- return NULL;
-
- *dst = '\0';
- dst_buf->len = dst - dst_buf->base;
- return dst_buf;
-}
-
-static h2o_iovec_t *decode_string(h2o_mem_pool_t *pool, const uint8_t **src, const uint8_t *src_end, int is_header_name,
- const char **err_desc)
-{
- h2o_iovec_t *ret;
- int is_huffman;
- int32_t len;
-
- if (*src >= src_end)
- return NULL;
-
- is_huffman = (**src & 0x80) != 0;
- if ((len = decode_int(src, src_end, 7)) == -1)
- return NULL;
-
- if (is_huffman) {
- uint8_t hflags = 0;
- if (*src + len > src_end)
- return NULL;
- if ((ret = decode_huffman(pool, *src, len, &hflags)) == NULL)
- return NULL;
- if (is_header_name) {
- if (ret->len <= 0) {
- return NULL;
- }
- /* pseudo-headers are checked later in `decode_header` */
- if (hflags & NGHTTP2_HUFF_INVALID_FOR_HEADER_NAME && ret->base[0] != ':') {
- if (hflags & NGHTTP2_HUFF_UPPER_CASE_CHAR) {
- *err_desc = err_found_upper_case_in_header_name;
- return NULL;
- } else {
- *err_desc = soft_err_found_invalid_char_in_header_name;
- }
- }
- } else {
- if (hflags & NGHTTP2_HUFF_INVALID_FOR_HEADER_VALUE) {
- *err_desc = soft_err_found_invalid_char_in_header_value;
- }
- }
- } else {
- if (*src + len > src_end)
- return NULL;
- if (is_header_name) {
- /* pseudo-headers are checked later in `decode_header` */
- if (**src != (uint8_t)':') {
- *err_desc = validate_header_name((char *)*src, len);
- if (*err_desc == err_found_upper_case_in_header_name) {
- return NULL;
- }
- }
- } else {
- if (contains_invalid_field_value_char((char *)*src, len)) {
- *err_desc = soft_err_found_invalid_char_in_header_value;
- }
- }
- ret = alloc_buf(pool, len);
- memcpy(ret->base, *src, len);
- ret->base[len] = '\0';
- }
- *src += len;
-
- return ret;
-}
-
-static void header_table_evict_one(h2o_hpack_header_table_t *table)
-{
- struct st_h2o_hpack_header_table_entry_t *entry;
- assert(table->num_entries != 0);
-
- entry = h2o_hpack_header_table_get(table, --table->num_entries);
- table->hpack_size -= entry->name->len + entry->value->len + HEADER_TABLE_ENTRY_SIZE_OFFSET;
- if (!h2o_iovec_is_token(entry->name))
- h2o_mem_release_shared(entry->name);
- if (!value_is_part_of_static_table(entry->value))
- h2o_mem_release_shared(entry->value);
- memset(entry, 0, sizeof(*entry));
-}
-
-static struct st_h2o_hpack_header_table_entry_t *header_table_add(h2o_hpack_header_table_t *table, size_t size_add,
- size_t max_num_entries)
-{
- /* adjust the size */
- while (table->num_entries != 0 && table->hpack_size + size_add > table->hpack_capacity)
- header_table_evict_one(table);
- while (max_num_entries <= table->num_entries)
- header_table_evict_one(table);
- if (table->num_entries == 0) {
- assert(table->hpack_size == 0);
- if (size_add > table->hpack_capacity)
- return NULL;
- }
- table->hpack_size += size_add;
-
- /* grow the entries if full */
- if (table->num_entries == table->entry_capacity) {
- size_t new_capacity = table->num_entries * 2;
- if (new_capacity < 16)
- new_capacity = 16;
- struct st_h2o_hpack_header_table_entry_t *new_entries =
- h2o_mem_alloc(new_capacity * sizeof(struct st_h2o_hpack_header_table_entry_t));
- if (table->num_entries != 0) {
- size_t src_index = table->entry_start_index, dst_index = 0;
- do {
- new_entries[dst_index] = table->entries[src_index];
- ++dst_index;
- src_index = (src_index + 1) % table->entry_capacity;
- } while (dst_index != table->num_entries);
- }
- memset(new_entries + table->num_entries, 0, sizeof(*new_entries) * (new_capacity - table->num_entries));
- free(table->entries);
- table->entries = new_entries;
- table->entry_capacity = new_capacity;
- table->entry_start_index = 0;
- }
-
- ++table->num_entries;
- table->entry_start_index = (table->entry_start_index + table->entry_capacity - 1) % table->entry_capacity;
- return table->entries + table->entry_start_index;
-}
-
-static int decode_header(h2o_mem_pool_t *pool, struct st_h2o_decode_header_result_t *result,
- h2o_hpack_header_table_t *hpack_header_table, const uint8_t **const src, const uint8_t *src_end,
- const char **err_desc)
-{
- int32_t index = 0;
- int value_is_indexed = 0, do_index = 0;
-
-Redo:
- if (*src >= src_end)
- return H2O_HTTP2_ERROR_COMPRESSION;
-
- /* determine the mode and handle accordingly */
- if (**src >= 128) {
- /* indexed header field representation */
- if ((index = decode_int(src, src_end, 7)) <= 0)
- return H2O_HTTP2_ERROR_COMPRESSION;
- value_is_indexed = 1;
- } else if (**src >= 64) {
- /* literal header field with incremental handling */
- if (**src == 64) {
- ++*src;
- } else if ((index = decode_int(src, src_end, 6)) <= 0) {
- return H2O_HTTP2_ERROR_COMPRESSION;
- }
- do_index = 1;
- } else if (**src < 32) {
- /* literal header field without indexing / never indexed */
- if ((**src & 0xf) == 0) {
- ++*src;
- } else if ((index = decode_int(src, src_end, 4)) <= 0) {
- return H2O_HTTP2_ERROR_COMPRESSION;
- }
- } else {
- /* size update */
- int new_apacity;
- if ((new_apacity = decode_int(src, src_end, 5)) < 0) {
- return H2O_HTTP2_ERROR_COMPRESSION;
- }
- if (new_apacity > hpack_header_table->hpack_max_capacity) {
- return H2O_HTTP2_ERROR_COMPRESSION;
- }
- hpack_header_table->hpack_capacity = new_apacity;
- while (hpack_header_table->num_entries != 0 && hpack_header_table->hpack_size > hpack_header_table->hpack_capacity) {
- header_table_evict_one(hpack_header_table);
- }
- goto Redo;
- }
-
- /* determine the header */
- if (index > 0) {
- /* existing name (and value?) */
- if (index < HEADER_TABLE_OFFSET) {
- result->name = (h2o_iovec_t *)h2o_hpack_static_table[index - 1].name;
- if (value_is_indexed) {
- result->value = (h2o_iovec_t *)&h2o_hpack_static_table[index - 1].value;
- }
- } else if (index - HEADER_TABLE_OFFSET < hpack_header_table->num_entries) {
- struct st_h2o_hpack_header_table_entry_t *entry =
- h2o_hpack_header_table_get(hpack_header_table, index - HEADER_TABLE_OFFSET);
- *err_desc = entry->err_desc;
- result->name = entry->name;
- if (!h2o_iovec_is_token(result->name))
- h2o_mem_link_shared(pool, result->name);
- if (value_is_indexed) {
- result->value = entry->value;
- h2o_mem_link_shared(pool, result->value);
- }
- } else {
- return H2O_HTTP2_ERROR_COMPRESSION;
- }
- } else {
- /* non-existing name */
- const h2o_token_t *name_token;
- if ((result->name = decode_string(pool, src, src_end, 1, err_desc)) == NULL) {
- if (*err_desc == err_found_upper_case_in_header_name) {
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- return H2O_HTTP2_ERROR_COMPRESSION;
- }
- if (!*err_desc) {
- /* predefined header names should be interned */
- if ((name_token = h2o_lookup_token(result->name->base, result->name->len)) != NULL) {
- result->name = (h2o_iovec_t *)&name_token->buf;
- }
- }
- }
-
- /* determine the value (if necessary) */
- if (!value_is_indexed) {
- if ((result->value = decode_string(pool, src, src_end, 0, err_desc)) == NULL) {
- return H2O_HTTP2_ERROR_COMPRESSION;
- }
- }
-
- /* add the decoded header to the header table if necessary */
- if (do_index) {
- struct st_h2o_hpack_header_table_entry_t *entry =
- header_table_add(hpack_header_table, result->name->len + result->value->len + HEADER_TABLE_ENTRY_SIZE_OFFSET, SIZE_MAX);
- if (entry != NULL) {
- entry->err_desc = *err_desc;
- entry->name = result->name;
- if (!h2o_iovec_is_token(entry->name))
- h2o_mem_addref_shared(entry->name);
- entry->value = result->value;
- if (!value_is_part_of_static_table(entry->value))
- h2o_mem_addref_shared(entry->value);
- }
- }
-
- return *err_desc ? H2O_HTTP2_ERROR_INVALID_HEADER_CHAR : 0;
-}
-
-static uint8_t *encode_status(uint8_t *dst, int status)
-{
- /* see also: STATUS_HEADER_MAX_SIZE */
-
- assert(100 <= status && status <= 999);
-
- switch (status) {
-#define COMMON_CODE(code, st) \
- case st: \
- *dst++ = 0x80 | code; \
- break
- COMMON_CODE(8, 200);
- COMMON_CODE(9, 204);
- COMMON_CODE(10, 206);
- COMMON_CODE(11, 304);
- COMMON_CODE(12, 400);
- COMMON_CODE(13, 404);
- COMMON_CODE(14, 500);
-#undef COMMON_CODE
- default:
- /* use literal header field without indexing - indexed name */
- *dst++ = 8;
- *dst++ = 3;
- sprintf((char *)dst, "%d", status);
- dst += 3;
- break;
- }
-
- return dst;
-}
-
-static uint8_t *encode_content_length(uint8_t *dst, size_t value)
-{
- char buf[32], *p = buf + sizeof(buf);
- size_t l;
-
- do {
- *--p = '0' + value % 10;
- } while ((value /= 10) != 0);
- l = buf + sizeof(buf) - p;
- *dst++ = 0x0f;
- *dst++ = 0x0d;
- *dst++ = (uint8_t)l;
- memcpy(dst, p, l);
- dst += l;
-
- return dst;
-}
-
-void h2o_hpack_dispose_header_table(h2o_hpack_header_table_t *header_table)
-{
- if (header_table->num_entries != 0) {
- size_t index = header_table->entry_start_index;
- do {
- struct st_h2o_hpack_header_table_entry_t *entry = header_table->entries + index;
- if (!h2o_iovec_is_token(entry->name))
- h2o_mem_release_shared(entry->name);
- if (!value_is_part_of_static_table(entry->value))
- h2o_mem_release_shared(entry->value);
- index = (index + 1) % header_table->entry_capacity;
- } while (--header_table->num_entries != 0);
- }
- free(header_table->entries);
-}
-
-int h2o_hpack_parse_headers(h2o_req_t *req, h2o_hpack_header_table_t *header_table, const uint8_t *src, size_t len,
- int *pseudo_header_exists_map, size_t *content_length, h2o_cache_digests_t **digests,
- const char **err_desc)
-{
- const uint8_t *src_end = src + len;
-
- *content_length = SIZE_MAX;
-
- while (src != src_end) {
- struct st_h2o_decode_header_result_t r;
- const char *decode_err = NULL;
- int ret = decode_header(&req->pool, &r, header_table, &src, src_end, &decode_err);
- if (ret != 0) {
- if (ret == H2O_HTTP2_ERROR_INVALID_HEADER_CHAR) {
- /* this is a soft error, we continue parsing, but register only the first error */
- if (*err_desc == NULL) {
- *err_desc = decode_err;
- }
- } else {
- *err_desc = decode_err;
- return ret;
- }
- }
- if (r.name->base[0] == ':') {
- if (pseudo_header_exists_map != NULL) {
- /* FIXME validate the chars in the value (e.g. reject SP in path) */
- if (r.name == &H2O_TOKEN_AUTHORITY->buf) {
- /* FIXME should we perform this check? */
- if (req->input.authority.base != NULL)
- return H2O_HTTP2_ERROR_PROTOCOL;
- req->input.authority = *r.value;
- *pseudo_header_exists_map |= H2O_HPACK_PARSE_HEADERS_AUTHORITY_EXISTS;
- } else if (r.name == &H2O_TOKEN_METHOD->buf) {
- if (req->input.method.base != NULL)
- return H2O_HTTP2_ERROR_PROTOCOL;
- req->input.method = *r.value;
- *pseudo_header_exists_map |= H2O_HPACK_PARSE_HEADERS_METHOD_EXISTS;
- } else if (r.name == &H2O_TOKEN_PATH->buf) {
- if (req->input.path.base != NULL)
- return H2O_HTTP2_ERROR_PROTOCOL;
- req->input.path = *r.value;
- *pseudo_header_exists_map |= H2O_HPACK_PARSE_HEADERS_PATH_EXISTS;
- } else if (r.name == &H2O_TOKEN_SCHEME->buf) {
- if (req->input.scheme != NULL)
- return H2O_HTTP2_ERROR_PROTOCOL;
- if (h2o_memis(r.value->base, r.value->len, H2O_STRLIT("https"))) {
- req->input.scheme = &H2O_URL_SCHEME_HTTPS;
- } else {
- /* draft-16 8.1.2.3 suggests quote: ":scheme is not restricted to http and https schemed URIs" */
- req->input.scheme = &H2O_URL_SCHEME_HTTP;
- }
- *pseudo_header_exists_map |= H2O_HPACK_PARSE_HEADERS_SCHEME_EXISTS;
- } else {
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- } else {
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- } else {
- pseudo_header_exists_map = NULL;
- if (h2o_iovec_is_token(r.name)) {
- h2o_token_t *token = H2O_STRUCT_FROM_MEMBER(h2o_token_t, buf, r.name);
- if (token == H2O_TOKEN_CONTENT_LENGTH) {
- if ((*content_length = h2o_strtosize(r.value->base, r.value->len)) == SIZE_MAX)
- return H2O_HTTP2_ERROR_PROTOCOL;
- } else {
- /* reject headers as defined in draft-16 8.1.2.2 */
- if (token->http2_should_reject) {
- if (token == H2O_TOKEN_HOST) {
- /* just skip (and :authority is used) */
- goto Next;
- } else if (token == H2O_TOKEN_TE && h2o_lcstris(r.value->base, r.value->len, H2O_STRLIT("trailers"))) {
- /* do not reject */
- } else {
- return H2O_HTTP2_ERROR_PROTOCOL;
- }
- }
- if (token == H2O_TOKEN_CACHE_DIGEST && digests != NULL) {
- /* TODO cache the decoded result in HPACK, as well as delay the decoding of the digest until being used */
- h2o_cache_digests_load_header(digests, r.value->base, r.value->len);
- }
- h2o_add_header(&req->pool, &req->headers, token, NULL, r.value->base, r.value->len);
- }
- } else {
- h2o_add_header_by_str(&req->pool, &req->headers, r.name->base, r.name->len, 0, NULL, r.value->base, r.value->len);
- }
- }
- Next:;
- }
-
- if (*err_desc) {
- return H2O_HTTP2_ERROR_INVALID_HEADER_CHAR;
- }
- return 0;
-}
-
-static inline int encode_int_is_onebyte(uint32_t value, size_t prefix_bits)
-{
- return value < (1 << prefix_bits) - 1;
-}
-
-static uint8_t *encode_int(uint8_t *dst, uint32_t value, size_t prefix_bits)
-{
- if (encode_int_is_onebyte(value, prefix_bits)) {
- *dst++ |= value;
- } else {
- /* see also: MAX_ENCODE_INT_LENGTH */
- value -= (1 << prefix_bits) - 1;
- if (value > 0x0fffffff)
- h2o_fatal("value out of range");
- *dst++ |= (1 << prefix_bits) - 1;
- for (; value >= 128; value >>= 7) {
- *dst++ = 0x80 | value;
- }
- *dst++ = value;
- }
- return dst;
-}
-
-static size_t encode_huffman(uint8_t *_dst, const uint8_t *src, size_t len)
-{
- uint8_t *dst = _dst, *dst_end = dst + len;
- const uint8_t *src_end = src + len;
- uint64_t bits = 0;
- int bits_left = 40;
-
- while (src != src_end) {
- const nghttp2_huff_sym *sym = huff_sym_table + *src++;
- bits |= (uint64_t)sym->code << (bits_left - sym->nbits);
- bits_left -= sym->nbits;
- while (bits_left <= 32) {
- *dst++ = bits >> 32;
- bits <<= 8;
- bits_left += 8;
- if (dst == dst_end) {
- return 0;
- }
- }
- }
-
- if (bits_left != 40) {
- bits |= ((uint64_t)1 << bits_left) - 1;
- *dst++ = bits >> 32;
- }
- if (dst == dst_end) {
- return 0;
- }
-
- return dst - _dst;
-}
-
-static size_t encode_as_is(uint8_t *dst, const char *s, size_t len)
-{
- uint8_t *start = dst;
- *dst = '\0';
- dst = encode_int(dst, (uint32_t)len, 7);
- memcpy(dst, s, len);
- dst += len;
- return dst - start;
-}
-
-size_t h2o_hpack_encode_string(uint8_t *dst, const char *s, size_t len)
-{
- if (H2O_LIKELY(len != 0)) {
- /* try to encode using huffman */
- size_t hufflen = encode_huffman(dst + 1, (const uint8_t *)s, len);
- if (H2O_LIKELY(hufflen != 0)) {
- size_t head_len;
- if (H2O_LIKELY(encode_int_is_onebyte((uint32_t)hufflen, 7))) {
- dst[0] = (uint8_t)(0x80 | hufflen);
- head_len = 1;
- } else {
- uint8_t head[8];
- head[0] = '\x80';
- head_len = encode_int(head, (uint32_t)hufflen, 7) - head;
- memmove(dst + head_len, dst + 1, hufflen);
- memcpy(dst, head, head_len);
- }
- return head_len + hufflen;
- }
- }
- return encode_as_is(dst, s, len);
-}
-
-static uint8_t *encode_header(h2o_hpack_header_table_t *header_table, uint8_t *dst, const h2o_iovec_t *name,
- const h2o_iovec_t *value)
-{
- int name_index = 0, dont_compress = 0, name_is_token = h2o_iovec_is_token(name);
-
- /* try to send as indexed */
- {
- size_t header_table_index = header_table->entry_start_index, n;
- for (n = header_table->num_entries; n != 0; --n) {
- struct st_h2o_hpack_header_table_entry_t *entry = header_table->entries + header_table_index;
- if (name_is_token) {
- if (name != entry->name)
- goto Next;
- } else {
- if (!h2o_memis(name->base, name->len, entry->name->base, entry->name->len))
- goto Next;
- if (name_index == 0)
- name_index = (int)(header_table->num_entries - n + HEADER_TABLE_OFFSET);
- }
- /* name matched! */
- if (!h2o_memis(value->base, value->len, entry->value->base, entry->value->len))
- goto Next;
- /* name and value matched! */
- *dst = 0x80;
- dst = encode_int(dst, (uint32_t)(header_table->num_entries - n + HEADER_TABLE_OFFSET), 7);
- return dst;
- Next:
- ++header_table_index;
- if (header_table_index == header_table->entry_capacity)
- header_table_index = 0;
- }
- }
-
- if (name_is_token) {
- const h2o_token_t *name_token = H2O_STRUCT_FROM_MEMBER(h2o_token_t, buf, name);
- name_index = name_token->http2_static_table_name_index;
- dont_compress = (name_token->dont_compress == 1 && value->len < 20) ? 1 : 0;
- }
-
- if (name_index != 0) {
- /* literal header field with indexing (indexed name). */
- if (dont_compress == 1) {
- /* mark the field as 'never indexed' */
- *dst = 0x10;
- dst = encode_int(dst, name_index, 4);
- } else {
- *dst = 0x40;
- dst = encode_int(dst, name_index, 6);
- }
- } else {
- /* literal header field with indexing (new name) */
- *dst++ = 0x40;
- dst += h2o_hpack_encode_string(dst, name->base, name->len);
- }
- if (dont_compress == 1) {
- /* bypass huffman encoding */
- dst += encode_as_is(dst, value->base, value->len);
- } else {
- /* add to header table (maximum number of entries in output header table is limited to 32 so that the search (see above) would
- not take too long) */
- dst += h2o_hpack_encode_string(dst, value->base, value->len);
- struct st_h2o_hpack_header_table_entry_t *entry =
- header_table_add(header_table, name->len + value->len + HEADER_TABLE_ENTRY_SIZE_OFFSET, 32);
- if (entry != NULL) {
- if (name_is_token) {
- entry->name = (h2o_iovec_t *)name;
- } else {
- entry->name = alloc_buf(NULL, name->len);
- entry->name->base[name->len] = '\0';
- memcpy(entry->name->base, name->base, name->len);
- }
- entry->value = alloc_buf(NULL, value->len);
- entry->value->base[value->len] = '\0';
- memcpy(entry->value->base, value->base, value->len);
- }
- }
-
- return dst;
-}
-
-static uint8_t *encode_method(h2o_hpack_header_table_t *header_table, uint8_t *dst, h2o_iovec_t value)
-{
- if (h2o_memis(value.base, value.len, H2O_STRLIT("GET"))) {
- *dst++ = 0x82;
- return dst;
- }
- if (h2o_memis(value.base, value.len, H2O_STRLIT("POST"))) {
- *dst++ = 0x83;
- return dst;
- }
- return encode_header(header_table, dst, &H2O_TOKEN_METHOD->buf, &value);
-}
-
-static uint8_t *encode_scheme(h2o_hpack_header_table_t *header_table, uint8_t *dst, const h2o_url_scheme_t *scheme)
-{
- if (scheme == &H2O_URL_SCHEME_HTTPS) {
- *dst++ = 0x87;
- return dst;
- }
- if (scheme == &H2O_URL_SCHEME_HTTP) {
- *dst++ = 0x86;
- return dst;
- }
- return encode_header(header_table, dst, &H2O_TOKEN_SCHEME->buf, &scheme->name);
-}
-
-static uint8_t *encode_path(h2o_hpack_header_table_t *header_table, uint8_t *dst, h2o_iovec_t value)
-{
- if (h2o_memis(value.base, value.len, H2O_STRLIT("/"))) {
- *dst++ = 0x84;
- return dst;
- }
- if (h2o_memis(value.base, value.len, H2O_STRLIT("/index.html"))) {
- *dst++ = 0x85;
- return dst;
- }
- return encode_header(header_table, dst, &H2O_TOKEN_PATH->buf, &value);
-}
-
-static uint8_t *encode_literal_header_without_indexing(uint8_t *dst, const h2o_iovec_t *name, const h2o_iovec_t *value)
-{
- /* literal header field without indexing / never indexed */
- *dst++ = 0;
- dst += h2o_hpack_encode_string(dst, name->base, name->len);
- dst += h2o_hpack_encode_string(dst, value->base, value->len);
- return dst;
-}
-
-static size_t calc_capacity(size_t name_len, size_t value_len)
-{
- return name_len + value_len + 1 + H2O_HTTP2_ENCODE_INT_MAX_LENGTH * 2;
-}
-
-static size_t calc_headers_capacity(const h2o_header_t *headers, size_t num_headers)
-{
- const h2o_header_t *header;
- size_t capacity = 0;
- for (header = headers; num_headers != 0; ++header, --num_headers)
- capacity += calc_capacity(header->name->len, header->value.len);
- return capacity;
-}
-
-static void fixup_frame_headers(h2o_buffer_t **buf, size_t start_at, uint8_t type, uint32_t stream_id, size_t max_frame_size)
-{
- /* try to fit all data into single frame, using the preallocated space for the frame header */
- size_t payload_size = (*buf)->size - start_at - H2O_HTTP2_FRAME_HEADER_SIZE;
- if (payload_size <= max_frame_size) {
- h2o_http2_encode_frame_header((uint8_t *)((*buf)->bytes + start_at), payload_size, type, H2O_HTTP2_FRAME_FLAG_END_HEADERS,
- stream_id);
- return;
- }
-
- /* need to setup continuation frames */
- size_t off;
- h2o_http2_encode_frame_header((uint8_t *)((*buf)->bytes + start_at), max_frame_size, type, 0, stream_id);
- off = start_at + H2O_HTTP2_FRAME_HEADER_SIZE + max_frame_size;
- while (1) {
- size_t left = (*buf)->size - off;
- h2o_buffer_reserve(buf, H2O_HTTP2_FRAME_HEADER_SIZE);
- memmove((*buf)->bytes + off + H2O_HTTP2_FRAME_HEADER_SIZE, (*buf)->bytes + off, left);
- (*buf)->size += H2O_HTTP2_FRAME_HEADER_SIZE;
- if (left <= max_frame_size) {
- h2o_http2_encode_frame_header((uint8_t *)((*buf)->bytes + off), left, H2O_HTTP2_FRAME_TYPE_CONTINUATION,
- H2O_HTTP2_FRAME_FLAG_END_HEADERS, stream_id);
- break;
- } else {
- h2o_http2_encode_frame_header((uint8_t *)((*buf)->bytes + off), max_frame_size, H2O_HTTP2_FRAME_TYPE_CONTINUATION, 0,
- stream_id);
- off += H2O_HTTP2_FRAME_HEADER_SIZE + max_frame_size;
- }
- }
-}
-
-void h2o_hpack_flatten_request(h2o_buffer_t **buf, h2o_hpack_header_table_t *header_table, uint32_t stream_id,
- size_t max_frame_size, h2o_req_t *req, uint32_t parent_stream_id)
-{
- size_t capacity = calc_headers_capacity(req->headers.entries, req->headers.size);
- capacity += H2O_HTTP2_FRAME_HEADER_SIZE /* first frame header */
- + 4; /* promised stream id */
- capacity += calc_capacity(H2O_TOKEN_METHOD->buf.len, req->input.method.len);
- capacity += calc_capacity(H2O_TOKEN_SCHEME->buf.len, req->input.scheme->name.len);
- capacity += calc_capacity(H2O_TOKEN_AUTHORITY->buf.len, req->input.authority.len);
- capacity += calc_capacity(H2O_TOKEN_PATH->buf.len, req->input.path.len);
-
- size_t start_at = (*buf)->size;
- uint8_t *dst = (void *)(h2o_buffer_reserve(buf, capacity).base + H2O_HTTP2_FRAME_HEADER_SIZE);
-
- /* encode */
- dst = h2o_http2_encode32u(dst, stream_id);
- dst = encode_method(header_table, dst, req->input.method);
- dst = encode_scheme(header_table, dst, req->input.scheme);
- dst = encode_header(header_table, dst, &H2O_TOKEN_AUTHORITY->buf, &req->input.authority);
- dst = encode_path(header_table, dst, req->input.path);
- size_t i;
- for (i = 0; i != req->headers.size; ++i) {
- const h2o_header_t *header = req->headers.entries + i;
- if (header->name == &H2O_TOKEN_ACCEPT_ENCODING->buf &&
- h2o_memis(header->value.base, header->value.len, H2O_STRLIT("gzip, deflate"))) {
- *dst++ = 0x90;
- } else {
- dst = encode_header(header_table, dst, header->name, &header->value);
- }
- }
- (*buf)->size = (char *)dst - (*buf)->bytes;
-
- /* setup the frame headers */
- fixup_frame_headers(buf, start_at, H2O_HTTP2_FRAME_TYPE_PUSH_PROMISE, parent_stream_id, max_frame_size);
-}
-
-void h2o_hpack_flatten_response(h2o_buffer_t **buf, h2o_hpack_header_table_t *header_table, uint32_t stream_id,
- size_t max_frame_size, h2o_res_t *res, h2o_timestamp_t *ts, const h2o_iovec_t *server_name,
- size_t content_length)
-{
- size_t capacity = calc_headers_capacity(res->headers.entries, res->headers.size);
- capacity += H2O_HTTP2_FRAME_HEADER_SIZE; /* for the first header */
- capacity += STATUS_HEADER_MAX_SIZE; /* for :status: */
-#ifndef H2O_UNITTEST
- capacity += 2 + H2O_TIMESTR_RFC1123_LEN; /* for Date: */
- if (server_name->len) {
- capacity += 5 + server_name->len; /* for Server: */
- }
-#endif
- if (content_length != SIZE_MAX)
- capacity += CONTENT_LENGTH_HEADER_MAX_SIZE; /* for content-length: UINT64_MAX (with huffman compression applied) */
-
- size_t start_at = (*buf)->size;
- uint8_t *dst = (void *)(h2o_buffer_reserve(buf, capacity).base + H2O_HTTP2_FRAME_HEADER_SIZE); /* skip frame header */
-
- /* encode */
- dst = encode_status(dst, res->status);
-#ifndef H2O_UNITTEST
- /* TODO keep some kind of reference to the indexed headers of Server and Date, and reuse them */
- if (server_name->len) {
- dst = encode_header(header_table, dst, &H2O_TOKEN_SERVER->buf, server_name);
- }
- h2o_iovec_t date_value = {ts->str->rfc1123, H2O_TIMESTR_RFC1123_LEN};
- dst = encode_header(header_table, dst, &H2O_TOKEN_DATE->buf, &date_value);
-#endif
- size_t i;
- for (i = 0; i != res->headers.size; ++i)
- dst = encode_header(header_table, dst, res->headers.entries[i].name, &res->headers.entries[i].value);
- if (content_length != SIZE_MAX)
- dst = encode_content_length(dst, content_length);
- (*buf)->size = (char *)dst - (*buf)->bytes;
-
- /* setup the frame headers */
- fixup_frame_headers(buf, start_at, H2O_HTTP2_FRAME_TYPE_HEADERS, stream_id, max_frame_size);
-}
diff --git a/web/server/h2o/libh2o/lib/http2/hpack_huffman_table.h b/web/server/h2o/libh2o/lib/http2/hpack_huffman_table.h
deleted file mode 100644
index 8f6afab90..000000000
--- a/web/server/h2o/libh2o/lib/http2/hpack_huffman_table.h
+++ /dev/null
@@ -1,4954 +0,0 @@
-// !!! DO NOT EDIT !!! Generated by misc/mkhufftbl.c
-/*
- * The MIT License
- *
- * Copyright (c) 2012, 2014, 2015, 2016 Tatsuhiro Tsujikawa
- * Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
- * Copyright (c) 2016 Fastly, Inc.
- *
- * 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.
- */
-
-typedef struct {
- uint32_t nbits;
- uint32_t code;
-} nghttp2_huff_sym;
-
-static const nghttp2_huff_sym huff_sym_table[] = {
- {13, 0x1ff8u}, {23, 0x7fffd8u}, {28, 0xfffffe2u}, {28, 0xfffffe3u}, {28, 0xfffffe4u}, {28, 0xfffffe5u}, {28, 0xfffffe6u},
- {28, 0xfffffe7u}, {28, 0xfffffe8u}, {24, 0xffffeau}, {30, 0x3ffffffcu}, {28, 0xfffffe9u}, {28, 0xfffffeau}, {30, 0x3ffffffdu},
- {28, 0xfffffebu}, {28, 0xfffffecu}, {28, 0xfffffedu}, {28, 0xfffffeeu}, {28, 0xfffffefu}, {28, 0xffffff0u}, {28, 0xffffff1u},
- {28, 0xffffff2u}, {30, 0x3ffffffeu}, {28, 0xffffff3u}, {28, 0xffffff4u}, {28, 0xffffff5u}, {28, 0xffffff6u}, {28, 0xffffff7u},
- {28, 0xffffff8u}, {28, 0xffffff9u}, {28, 0xffffffau}, {28, 0xffffffbu}, {6, 0x14u}, {10, 0x3f8u}, {10, 0x3f9u},
- {12, 0xffau}, {13, 0x1ff9u}, {6, 0x15u}, {8, 0xf8u}, {11, 0x7fau}, {10, 0x3fau}, {10, 0x3fbu},
- {8, 0xf9u}, {11, 0x7fbu}, {8, 0xfau}, {6, 0x16u}, {6, 0x17u}, {6, 0x18u}, {5, 0x0u},
- {5, 0x1u}, {5, 0x2u}, {6, 0x19u}, {6, 0x1au}, {6, 0x1bu}, {6, 0x1cu}, {6, 0x1du},
- {6, 0x1eu}, {6, 0x1fu}, {7, 0x5cu}, {8, 0xfbu}, {15, 0x7ffcu}, {6, 0x20u}, {12, 0xffbu},
- {10, 0x3fcu}, {13, 0x1ffau}, {6, 0x21u}, {7, 0x5du}, {7, 0x5eu}, {7, 0x5fu}, {7, 0x60u},
- {7, 0x61u}, {7, 0x62u}, {7, 0x63u}, {7, 0x64u}, {7, 0x65u}, {7, 0x66u}, {7, 0x67u},
- {7, 0x68u}, {7, 0x69u}, {7, 0x6au}, {7, 0x6bu}, {7, 0x6cu}, {7, 0x6du}, {7, 0x6eu},
- {7, 0x6fu}, {7, 0x70u}, {7, 0x71u}, {7, 0x72u}, {8, 0xfcu}, {7, 0x73u}, {8, 0xfdu},
- {13, 0x1ffbu}, {19, 0x7fff0u}, {13, 0x1ffcu}, {14, 0x3ffcu}, {6, 0x22u}, {15, 0x7ffdu}, {5, 0x3u},
- {6, 0x23u}, {5, 0x4u}, {6, 0x24u}, {5, 0x5u}, {6, 0x25u}, {6, 0x26u}, {6, 0x27u},
- {5, 0x6u}, {7, 0x74u}, {7, 0x75u}, {6, 0x28u}, {6, 0x29u}, {6, 0x2au}, {5, 0x7u},
- {6, 0x2bu}, {7, 0x76u}, {6, 0x2cu}, {5, 0x8u}, {5, 0x9u}, {6, 0x2du}, {7, 0x77u},
- {7, 0x78u}, {7, 0x79u}, {7, 0x7au}, {7, 0x7bu}, {15, 0x7ffeu}, {11, 0x7fcu}, {14, 0x3ffdu},
- {13, 0x1ffdu}, {28, 0xffffffcu}, {20, 0xfffe6u}, {22, 0x3fffd2u}, {20, 0xfffe7u}, {20, 0xfffe8u}, {22, 0x3fffd3u},
- {22, 0x3fffd4u}, {22, 0x3fffd5u}, {23, 0x7fffd9u}, {22, 0x3fffd6u}, {23, 0x7fffdau}, {23, 0x7fffdbu}, {23, 0x7fffdcu},
- {23, 0x7fffddu}, {23, 0x7fffdeu}, {24, 0xffffebu}, {23, 0x7fffdfu}, {24, 0xffffecu}, {24, 0xffffedu}, {22, 0x3fffd7u},
- {23, 0x7fffe0u}, {24, 0xffffeeu}, {23, 0x7fffe1u}, {23, 0x7fffe2u}, {23, 0x7fffe3u}, {23, 0x7fffe4u}, {21, 0x1fffdcu},
- {22, 0x3fffd8u}, {23, 0x7fffe5u}, {22, 0x3fffd9u}, {23, 0x7fffe6u}, {23, 0x7fffe7u}, {24, 0xffffefu}, {22, 0x3fffdau},
- {21, 0x1fffddu}, {20, 0xfffe9u}, {22, 0x3fffdbu}, {22, 0x3fffdcu}, {23, 0x7fffe8u}, {23, 0x7fffe9u}, {21, 0x1fffdeu},
- {23, 0x7fffeau}, {22, 0x3fffddu}, {22, 0x3fffdeu}, {24, 0xfffff0u}, {21, 0x1fffdfu}, {22, 0x3fffdfu}, {23, 0x7fffebu},
- {23, 0x7fffecu}, {21, 0x1fffe0u}, {21, 0x1fffe1u}, {22, 0x3fffe0u}, {21, 0x1fffe2u}, {23, 0x7fffedu}, {22, 0x3fffe1u},
- {23, 0x7fffeeu}, {23, 0x7fffefu}, {20, 0xfffeau}, {22, 0x3fffe2u}, {22, 0x3fffe3u}, {22, 0x3fffe4u}, {23, 0x7ffff0u},
- {22, 0x3fffe5u}, {22, 0x3fffe6u}, {23, 0x7ffff1u}, {26, 0x3ffffe0u}, {26, 0x3ffffe1u}, {20, 0xfffebu}, {19, 0x7fff1u},
- {22, 0x3fffe7u}, {23, 0x7ffff2u}, {22, 0x3fffe8u}, {25, 0x1ffffecu}, {26, 0x3ffffe2u}, {26, 0x3ffffe3u}, {26, 0x3ffffe4u},
- {27, 0x7ffffdeu}, {27, 0x7ffffdfu}, {26, 0x3ffffe5u}, {24, 0xfffff1u}, {25, 0x1ffffedu}, {19, 0x7fff2u}, {21, 0x1fffe3u},
- {26, 0x3ffffe6u}, {27, 0x7ffffe0u}, {27, 0x7ffffe1u}, {26, 0x3ffffe7u}, {27, 0x7ffffe2u}, {24, 0xfffff2u}, {21, 0x1fffe4u},
- {21, 0x1fffe5u}, {26, 0x3ffffe8u}, {26, 0x3ffffe9u}, {28, 0xffffffdu}, {27, 0x7ffffe3u}, {27, 0x7ffffe4u}, {27, 0x7ffffe5u},
- {20, 0xfffecu}, {24, 0xfffff3u}, {20, 0xfffedu}, {21, 0x1fffe6u}, {22, 0x3fffe9u}, {21, 0x1fffe7u}, {21, 0x1fffe8u},
- {23, 0x7ffff3u}, {22, 0x3fffeau}, {22, 0x3fffebu}, {25, 0x1ffffeeu}, {25, 0x1ffffefu}, {24, 0xfffff4u}, {24, 0xfffff5u},
- {26, 0x3ffffeau}, {23, 0x7ffff4u}, {26, 0x3ffffebu}, {27, 0x7ffffe6u}, {26, 0x3ffffecu}, {26, 0x3ffffedu}, {27, 0x7ffffe7u},
- {27, 0x7ffffe8u}, {27, 0x7ffffe9u}, {27, 0x7ffffeau}, {27, 0x7ffffebu}, {28, 0xffffffeu}, {27, 0x7ffffecu}, {27, 0x7ffffedu},
- {27, 0x7ffffeeu}, {27, 0x7ffffefu}, {27, 0x7fffff0u}, {26, 0x3ffffeeu}, {30, 0x3fffffffu}};
-
-typedef enum {
- NGHTTP2_HUFF_ACCEPTED = 1,
- NGHTTP2_HUFF_SYM = 2,
- NGHTTP2_HUFF_FAIL = 4,
- NGHTTP2_HUFF_INVALID_FOR_HEADER_NAME = 8,
- NGHTTP2_HUFF_INVALID_FOR_HEADER_VALUE = 16,
- NGHTTP2_HUFF_UPPER_CASE_CHAR = 32,
-#define NGHTTP2_HUFF_INVALID_CHARS (NGHTTP2_HUFF_INVALID_FOR_HEADER_NAME | NGHTTP2_HUFF_INVALID_FOR_HEADER_VALUE)
-} nghttp2_huff_decode_flag;
-
-typedef struct {
- uint8_t state;
- uint8_t flags;
- uint8_t sym;
-} nghttp2_huff_decode;
-
-static const nghttp2_huff_decode huff_decode_table[][16] = {
- /* 0 */
- {
- {4, 0x00, 0},
- {5, 0x00, 0},
- {7, 0x00, 0},
- {8, 0x00, 0},
- {11, 0x00, 0},
- {12, 0x00, 0},
- {16, 0x00, 0},
- {19, 0x00, 0},
- {25, 0x00, 0},
- {28, 0x00, 0},
- {32, 0x00, 0},
- {35, 0x00, 0},
- {42, 0x00, 0},
- {49, 0x00, 0},
- {57, 0x00, 0},
- {64, 0x01, 0},
- },
- /* 1 */
- {
- {0, 0x03, 48},
- {0, 0x03, 49},
- {0, 0x03, 50},
- {0, 0x03, 97},
- {0, 0x03, 99},
- {0, 0x03, 101},
- {0, 0x03, 105},
- {0, 0x03, 111},
- {0, 0x03, 115},
- {0, 0x03, 116},
- {13, 0x00, 0},
- {14, 0x00, 0},
- {17, 0x00, 0},
- {18, 0x00, 0},
- {20, 0x00, 0},
- {21, 0x00, 0},
- },
- /* 2 */
- {
- {1, 0x02, 48},
- {22, 0x03, 48},
- {1, 0x02, 49},
- {22, 0x03, 49},
- {1, 0x02, 50},
- {22, 0x03, 50},
- {1, 0x02, 97},
- {22, 0x03, 97},
- {1, 0x02, 99},
- {22, 0x03, 99},
- {1, 0x02, 101},
- {22, 0x03, 101},
- {1, 0x02, 105},
- {22, 0x03, 105},
- {1, 0x02, 111},
- {22, 0x03, 111},
- },
- /* 3 */
- {
- {2, 0x02, 48},
- {9, 0x02, 48},
- {23, 0x02, 48},
- {40, 0x03, 48},
- {2, 0x02, 49},
- {9, 0x02, 49},
- {23, 0x02, 49},
- {40, 0x03, 49},
- {2, 0x02, 50},
- {9, 0x02, 50},
- {23, 0x02, 50},
- {40, 0x03, 50},
- {2, 0x02, 97},
- {9, 0x02, 97},
- {23, 0x02, 97},
- {40, 0x03, 97},
- },
- /* 4 */
- {
- {3, 0x02, 48},
- {6, 0x02, 48},
- {10, 0x02, 48},
- {15, 0x02, 48},
- {24, 0x02, 48},
- {31, 0x02, 48},
- {41, 0x02, 48},
- {56, 0x03, 48},
- {3, 0x02, 49},
- {6, 0x02, 49},
- {10, 0x02, 49},
- {15, 0x02, 49},
- {24, 0x02, 49},
- {31, 0x02, 49},
- {41, 0x02, 49},
- {56, 0x03, 49},
- },
- /* 5 */
- {
- {3, 0x02, 50},
- {6, 0x02, 50},
- {10, 0x02, 50},
- {15, 0x02, 50},
- {24, 0x02, 50},
- {31, 0x02, 50},
- {41, 0x02, 50},
- {56, 0x03, 50},
- {3, 0x02, 97},
- {6, 0x02, 97},
- {10, 0x02, 97},
- {15, 0x02, 97},
- {24, 0x02, 97},
- {31, 0x02, 97},
- {41, 0x02, 97},
- {56, 0x03, 97},
- },
- /* 6 */
- {
- {2, 0x02, 99},
- {9, 0x02, 99},
- {23, 0x02, 99},
- {40, 0x03, 99},
- {2, 0x02, 101},
- {9, 0x02, 101},
- {23, 0x02, 101},
- {40, 0x03, 101},
- {2, 0x02, 105},
- {9, 0x02, 105},
- {23, 0x02, 105},
- {40, 0x03, 105},
- {2, 0x02, 111},
- {9, 0x02, 111},
- {23, 0x02, 111},
- {40, 0x03, 111},
- },
- /* 7 */
- {
- {3, 0x02, 99},
- {6, 0x02, 99},
- {10, 0x02, 99},
- {15, 0x02, 99},
- {24, 0x02, 99},
- {31, 0x02, 99},
- {41, 0x02, 99},
- {56, 0x03, 99},
- {3, 0x02, 101},
- {6, 0x02, 101},
- {10, 0x02, 101},
- {15, 0x02, 101},
- {24, 0x02, 101},
- {31, 0x02, 101},
- {41, 0x02, 101},
- {56, 0x03, 101},
- },
- /* 8 */
- {
- {3, 0x02, 105},
- {6, 0x02, 105},
- {10, 0x02, 105},
- {15, 0x02, 105},
- {24, 0x02, 105},
- {31, 0x02, 105},
- {41, 0x02, 105},
- {56, 0x03, 105},
- {3, 0x02, 111},
- {6, 0x02, 111},
- {10, 0x02, 111},
- {15, 0x02, 111},
- {24, 0x02, 111},
- {31, 0x02, 111},
- {41, 0x02, 111},
- {56, 0x03, 111},
- },
- /* 9 */
- {
- {1, 0x02, 115},
- {22, 0x03, 115},
- {1, 0x02, 116},
- {22, 0x03, 116},
- {0, 0x0b, 32},
- {0, 0x03, 37},
- {0, 0x03, 45},
- {0, 0x03, 46},
- {0, 0x0b, 47},
- {0, 0x03, 51},
- {0, 0x03, 52},
- {0, 0x03, 53},
- {0, 0x03, 54},
- {0, 0x03, 55},
- {0, 0x03, 56},
- {0, 0x03, 57},
- },
- /* 10 */
- {
- {2, 0x02, 115},
- {9, 0x02, 115},
- {23, 0x02, 115},
- {40, 0x03, 115},
- {2, 0x02, 116},
- {9, 0x02, 116},
- {23, 0x02, 116},
- {40, 0x03, 116},
- {1, 0x0a, 32},
- {22, 0x0b, 32},
- {1, 0x02, 37},
- {22, 0x03, 37},
- {1, 0x02, 45},
- {22, 0x03, 45},
- {1, 0x02, 46},
- {22, 0x03, 46},
- },
- /* 11 */
- {
- {3, 0x02, 115},
- {6, 0x02, 115},
- {10, 0x02, 115},
- {15, 0x02, 115},
- {24, 0x02, 115},
- {31, 0x02, 115},
- {41, 0x02, 115},
- {56, 0x03, 115},
- {3, 0x02, 116},
- {6, 0x02, 116},
- {10, 0x02, 116},
- {15, 0x02, 116},
- {24, 0x02, 116},
- {31, 0x02, 116},
- {41, 0x02, 116},
- {56, 0x03, 116},
- },
- /* 12 */
- {
- {2, 0x0a, 32},
- {9, 0x0a, 32},
- {23, 0x0a, 32},
- {40, 0x0b, 32},
- {2, 0x02, 37},
- {9, 0x02, 37},
- {23, 0x02, 37},
- {40, 0x03, 37},
- {2, 0x02, 45},
- {9, 0x02, 45},
- {23, 0x02, 45},
- {40, 0x03, 45},
- {2, 0x02, 46},
- {9, 0x02, 46},
- {23, 0x02, 46},
- {40, 0x03, 46},
- },
- /* 13 */
- {
- {3, 0x0a, 32},
- {6, 0x0a, 32},
- {10, 0x0a, 32},
- {15, 0x0a, 32},
- {24, 0x0a, 32},
- {31, 0x0a, 32},
- {41, 0x0a, 32},
- {56, 0x0b, 32},
- {3, 0x02, 37},
- {6, 0x02, 37},
- {10, 0x02, 37},
- {15, 0x02, 37},
- {24, 0x02, 37},
- {31, 0x02, 37},
- {41, 0x02, 37},
- {56, 0x03, 37},
- },
- /* 14 */
- {
- {3, 0x02, 45},
- {6, 0x02, 45},
- {10, 0x02, 45},
- {15, 0x02, 45},
- {24, 0x02, 45},
- {31, 0x02, 45},
- {41, 0x02, 45},
- {56, 0x03, 45},
- {3, 0x02, 46},
- {6, 0x02, 46},
- {10, 0x02, 46},
- {15, 0x02, 46},
- {24, 0x02, 46},
- {31, 0x02, 46},
- {41, 0x02, 46},
- {56, 0x03, 46},
- },
- /* 15 */
- {
- {1, 0x0a, 47},
- {22, 0x0b, 47},
- {1, 0x02, 51},
- {22, 0x03, 51},
- {1, 0x02, 52},
- {22, 0x03, 52},
- {1, 0x02, 53},
- {22, 0x03, 53},
- {1, 0x02, 54},
- {22, 0x03, 54},
- {1, 0x02, 55},
- {22, 0x03, 55},
- {1, 0x02, 56},
- {22, 0x03, 56},
- {1, 0x02, 57},
- {22, 0x03, 57},
- },
- /* 16 */
- {
- {2, 0x0a, 47},
- {9, 0x0a, 47},
- {23, 0x0a, 47},
- {40, 0x0b, 47},
- {2, 0x02, 51},
- {9, 0x02, 51},
- {23, 0x02, 51},
- {40, 0x03, 51},
- {2, 0x02, 52},
- {9, 0x02, 52},
- {23, 0x02, 52},
- {40, 0x03, 52},
- {2, 0x02, 53},
- {9, 0x02, 53},
- {23, 0x02, 53},
- {40, 0x03, 53},
- },
- /* 17 */
- {
- {3, 0x0a, 47},
- {6, 0x0a, 47},
- {10, 0x0a, 47},
- {15, 0x0a, 47},
- {24, 0x0a, 47},
- {31, 0x0a, 47},
- {41, 0x0a, 47},
- {56, 0x0b, 47},
- {3, 0x02, 51},
- {6, 0x02, 51},
- {10, 0x02, 51},
- {15, 0x02, 51},
- {24, 0x02, 51},
- {31, 0x02, 51},
- {41, 0x02, 51},
- {56, 0x03, 51},
- },
- /* 18 */
- {
- {3, 0x02, 52},
- {6, 0x02, 52},
- {10, 0x02, 52},
- {15, 0x02, 52},
- {24, 0x02, 52},
- {31, 0x02, 52},
- {41, 0x02, 52},
- {56, 0x03, 52},
- {3, 0x02, 53},
- {6, 0x02, 53},
- {10, 0x02, 53},
- {15, 0x02, 53},
- {24, 0x02, 53},
- {31, 0x02, 53},
- {41, 0x02, 53},
- {56, 0x03, 53},
- },
- /* 19 */
- {
- {2, 0x02, 54},
- {9, 0x02, 54},
- {23, 0x02, 54},
- {40, 0x03, 54},
- {2, 0x02, 55},
- {9, 0x02, 55},
- {23, 0x02, 55},
- {40, 0x03, 55},
- {2, 0x02, 56},
- {9, 0x02, 56},
- {23, 0x02, 56},
- {40, 0x03, 56},
- {2, 0x02, 57},
- {9, 0x02, 57},
- {23, 0x02, 57},
- {40, 0x03, 57},
- },
- /* 20 */
- {
- {3, 0x02, 54},
- {6, 0x02, 54},
- {10, 0x02, 54},
- {15, 0x02, 54},
- {24, 0x02, 54},
- {31, 0x02, 54},
- {41, 0x02, 54},
- {56, 0x03, 54},
- {3, 0x02, 55},
- {6, 0x02, 55},
- {10, 0x02, 55},
- {15, 0x02, 55},
- {24, 0x02, 55},
- {31, 0x02, 55},
- {41, 0x02, 55},
- {56, 0x03, 55},
- },
- /* 21 */
- {
- {3, 0x02, 56},
- {6, 0x02, 56},
- {10, 0x02, 56},
- {15, 0x02, 56},
- {24, 0x02, 56},
- {31, 0x02, 56},
- {41, 0x02, 56},
- {56, 0x03, 56},
- {3, 0x02, 57},
- {6, 0x02, 57},
- {10, 0x02, 57},
- {15, 0x02, 57},
- {24, 0x02, 57},
- {31, 0x02, 57},
- {41, 0x02, 57},
- {56, 0x03, 57},
- },
- /* 22 */
- {
- {26, 0x00, 0},
- {27, 0x00, 0},
- {29, 0x00, 0},
- {30, 0x00, 0},
- {33, 0x00, 0},
- {34, 0x00, 0},
- {36, 0x00, 0},
- {37, 0x00, 0},
- {43, 0x00, 0},
- {46, 0x00, 0},
- {50, 0x00, 0},
- {53, 0x00, 0},
- {58, 0x00, 0},
- {61, 0x00, 0},
- {65, 0x00, 0},
- {68, 0x01, 0},
- },
- /* 23 */
- {
- {0, 0x0b, 61},
- {0, 0x2b, 65},
- {0, 0x03, 95},
- {0, 0x03, 98},
- {0, 0x03, 100},
- {0, 0x03, 102},
- {0, 0x03, 103},
- {0, 0x03, 104},
- {0, 0x03, 108},
- {0, 0x03, 109},
- {0, 0x03, 110},
- {0, 0x03, 112},
- {0, 0x03, 114},
- {0, 0x03, 117},
- {38, 0x00, 0},
- {39, 0x00, 0},
- },
- /* 24 */
- {
- {1, 0x0a, 61},
- {22, 0x0b, 61},
- {1, 0x2a, 65},
- {22, 0x2b, 65},
- {1, 0x02, 95},
- {22, 0x03, 95},
- {1, 0x02, 98},
- {22, 0x03, 98},
- {1, 0x02, 100},
- {22, 0x03, 100},
- {1, 0x02, 102},
- {22, 0x03, 102},
- {1, 0x02, 103},
- {22, 0x03, 103},
- {1, 0x02, 104},
- {22, 0x03, 104},
- },
- /* 25 */
- {
- {2, 0x0a, 61},
- {9, 0x0a, 61},
- {23, 0x0a, 61},
- {40, 0x0b, 61},
- {2, 0x2a, 65},
- {9, 0x2a, 65},
- {23, 0x2a, 65},
- {40, 0x2b, 65},
- {2, 0x02, 95},
- {9, 0x02, 95},
- {23, 0x02, 95},
- {40, 0x03, 95},
- {2, 0x02, 98},
- {9, 0x02, 98},
- {23, 0x02, 98},
- {40, 0x03, 98},
- },
- /* 26 */
- {
- {3, 0x0a, 61},
- {6, 0x0a, 61},
- {10, 0x0a, 61},
- {15, 0x0a, 61},
- {24, 0x0a, 61},
- {31, 0x0a, 61},
- {41, 0x0a, 61},
- {56, 0x0b, 61},
- {3, 0x2a, 65},
- {6, 0x2a, 65},
- {10, 0x2a, 65},
- {15, 0x2a, 65},
- {24, 0x2a, 65},
- {31, 0x2a, 65},
- {41, 0x2a, 65},
- {56, 0x2b, 65},
- },
- /* 27 */
- {
- {3, 0x02, 95},
- {6, 0x02, 95},
- {10, 0x02, 95},
- {15, 0x02, 95},
- {24, 0x02, 95},
- {31, 0x02, 95},
- {41, 0x02, 95},
- {56, 0x03, 95},
- {3, 0x02, 98},
- {6, 0x02, 98},
- {10, 0x02, 98},
- {15, 0x02, 98},
- {24, 0x02, 98},
- {31, 0x02, 98},
- {41, 0x02, 98},
- {56, 0x03, 98},
- },
- /* 28 */
- {
- {2, 0x02, 100},
- {9, 0x02, 100},
- {23, 0x02, 100},
- {40, 0x03, 100},
- {2, 0x02, 102},
- {9, 0x02, 102},
- {23, 0x02, 102},
- {40, 0x03, 102},
- {2, 0x02, 103},
- {9, 0x02, 103},
- {23, 0x02, 103},
- {40, 0x03, 103},
- {2, 0x02, 104},
- {9, 0x02, 104},
- {23, 0x02, 104},
- {40, 0x03, 104},
- },
- /* 29 */
- {
- {3, 0x02, 100},
- {6, 0x02, 100},
- {10, 0x02, 100},
- {15, 0x02, 100},
- {24, 0x02, 100},
- {31, 0x02, 100},
- {41, 0x02, 100},
- {56, 0x03, 100},
- {3, 0x02, 102},
- {6, 0x02, 102},
- {10, 0x02, 102},
- {15, 0x02, 102},
- {24, 0x02, 102},
- {31, 0x02, 102},
- {41, 0x02, 102},
- {56, 0x03, 102},
- },
- /* 30 */
- {
- {3, 0x02, 103},
- {6, 0x02, 103},
- {10, 0x02, 103},
- {15, 0x02, 103},
- {24, 0x02, 103},
- {31, 0x02, 103},
- {41, 0x02, 103},
- {56, 0x03, 103},
- {3, 0x02, 104},
- {6, 0x02, 104},
- {10, 0x02, 104},
- {15, 0x02, 104},
- {24, 0x02, 104},
- {31, 0x02, 104},
- {41, 0x02, 104},
- {56, 0x03, 104},
- },
- /* 31 */
- {
- {1, 0x02, 108},
- {22, 0x03, 108},
- {1, 0x02, 109},
- {22, 0x03, 109},
- {1, 0x02, 110},
- {22, 0x03, 110},
- {1, 0x02, 112},
- {22, 0x03, 112},
- {1, 0x02, 114},
- {22, 0x03, 114},
- {1, 0x02, 117},
- {22, 0x03, 117},
- {0, 0x0b, 58},
- {0, 0x2b, 66},
- {0, 0x2b, 67},
- {0, 0x2b, 68},
- },
- /* 32 */
- {
- {2, 0x02, 108},
- {9, 0x02, 108},
- {23, 0x02, 108},
- {40, 0x03, 108},
- {2, 0x02, 109},
- {9, 0x02, 109},
- {23, 0x02, 109},
- {40, 0x03, 109},
- {2, 0x02, 110},
- {9, 0x02, 110},
- {23, 0x02, 110},
- {40, 0x03, 110},
- {2, 0x02, 112},
- {9, 0x02, 112},
- {23, 0x02, 112},
- {40, 0x03, 112},
- },
- /* 33 */
- {
- {3, 0x02, 108},
- {6, 0x02, 108},
- {10, 0x02, 108},
- {15, 0x02, 108},
- {24, 0x02, 108},
- {31, 0x02, 108},
- {41, 0x02, 108},
- {56, 0x03, 108},
- {3, 0x02, 109},
- {6, 0x02, 109},
- {10, 0x02, 109},
- {15, 0x02, 109},
- {24, 0x02, 109},
- {31, 0x02, 109},
- {41, 0x02, 109},
- {56, 0x03, 109},
- },
- /* 34 */
- {
- {3, 0x02, 110},
- {6, 0x02, 110},
- {10, 0x02, 110},
- {15, 0x02, 110},
- {24, 0x02, 110},
- {31, 0x02, 110},
- {41, 0x02, 110},
- {56, 0x03, 110},
- {3, 0x02, 112},
- {6, 0x02, 112},
- {10, 0x02, 112},
- {15, 0x02, 112},
- {24, 0x02, 112},
- {31, 0x02, 112},
- {41, 0x02, 112},
- {56, 0x03, 112},
- },
- /* 35 */
- {
- {2, 0x02, 114},
- {9, 0x02, 114},
- {23, 0x02, 114},
- {40, 0x03, 114},
- {2, 0x02, 117},
- {9, 0x02, 117},
- {23, 0x02, 117},
- {40, 0x03, 117},
- {1, 0x0a, 58},
- {22, 0x0b, 58},
- {1, 0x2a, 66},
- {22, 0x2b, 66},
- {1, 0x2a, 67},
- {22, 0x2b, 67},
- {1, 0x2a, 68},
- {22, 0x2b, 68},
- },
- /* 36 */
- {
- {3, 0x02, 114},
- {6, 0x02, 114},
- {10, 0x02, 114},
- {15, 0x02, 114},
- {24, 0x02, 114},
- {31, 0x02, 114},
- {41, 0x02, 114},
- {56, 0x03, 114},
- {3, 0x02, 117},
- {6, 0x02, 117},
- {10, 0x02, 117},
- {15, 0x02, 117},
- {24, 0x02, 117},
- {31, 0x02, 117},
- {41, 0x02, 117},
- {56, 0x03, 117},
- },
- /* 37 */
- {
- {2, 0x0a, 58},
- {9, 0x0a, 58},
- {23, 0x0a, 58},
- {40, 0x0b, 58},
- {2, 0x2a, 66},
- {9, 0x2a, 66},
- {23, 0x2a, 66},
- {40, 0x2b, 66},
- {2, 0x2a, 67},
- {9, 0x2a, 67},
- {23, 0x2a, 67},
- {40, 0x2b, 67},
- {2, 0x2a, 68},
- {9, 0x2a, 68},
- {23, 0x2a, 68},
- {40, 0x2b, 68},
- },
- /* 38 */
- {
- {3, 0x0a, 58},
- {6, 0x0a, 58},
- {10, 0x0a, 58},
- {15, 0x0a, 58},
- {24, 0x0a, 58},
- {31, 0x0a, 58},
- {41, 0x0a, 58},
- {56, 0x0b, 58},
- {3, 0x2a, 66},
- {6, 0x2a, 66},
- {10, 0x2a, 66},
- {15, 0x2a, 66},
- {24, 0x2a, 66},
- {31, 0x2a, 66},
- {41, 0x2a, 66},
- {56, 0x2b, 66},
- },
- /* 39 */
- {
- {3, 0x2a, 67},
- {6, 0x2a, 67},
- {10, 0x2a, 67},
- {15, 0x2a, 67},
- {24, 0x2a, 67},
- {31, 0x2a, 67},
- {41, 0x2a, 67},
- {56, 0x2b, 67},
- {3, 0x2a, 68},
- {6, 0x2a, 68},
- {10, 0x2a, 68},
- {15, 0x2a, 68},
- {24, 0x2a, 68},
- {31, 0x2a, 68},
- {41, 0x2a, 68},
- {56, 0x2b, 68},
- },
- /* 40 */
- {
- {44, 0x00, 0},
- {45, 0x00, 0},
- {47, 0x00, 0},
- {48, 0x00, 0},
- {51, 0x00, 0},
- {52, 0x00, 0},
- {54, 0x00, 0},
- {55, 0x00, 0},
- {59, 0x00, 0},
- {60, 0x00, 0},
- {62, 0x00, 0},
- {63, 0x00, 0},
- {66, 0x00, 0},
- {67, 0x00, 0},
- {69, 0x00, 0},
- {72, 0x01, 0},
- },
- /* 41 */
- {
- {0, 0x2b, 69},
- {0, 0x2b, 70},
- {0, 0x2b, 71},
- {0, 0x2b, 72},
- {0, 0x2b, 73},
- {0, 0x2b, 74},
- {0, 0x2b, 75},
- {0, 0x2b, 76},
- {0, 0x2b, 77},
- {0, 0x2b, 78},
- {0, 0x2b, 79},
- {0, 0x2b, 80},
- {0, 0x2b, 81},
- {0, 0x2b, 82},
- {0, 0x2b, 83},
- {0, 0x2b, 84},
- },
- /* 42 */
- {
- {1, 0x2a, 69},
- {22, 0x2b, 69},
- {1, 0x2a, 70},
- {22, 0x2b, 70},
- {1, 0x2a, 71},
- {22, 0x2b, 71},
- {1, 0x2a, 72},
- {22, 0x2b, 72},
- {1, 0x2a, 73},
- {22, 0x2b, 73},
- {1, 0x2a, 74},
- {22, 0x2b, 74},
- {1, 0x2a, 75},
- {22, 0x2b, 75},
- {1, 0x2a, 76},
- {22, 0x2b, 76},
- },
- /* 43 */
- {
- {2, 0x2a, 69},
- {9, 0x2a, 69},
- {23, 0x2a, 69},
- {40, 0x2b, 69},
- {2, 0x2a, 70},
- {9, 0x2a, 70},
- {23, 0x2a, 70},
- {40, 0x2b, 70},
- {2, 0x2a, 71},
- {9, 0x2a, 71},
- {23, 0x2a, 71},
- {40, 0x2b, 71},
- {2, 0x2a, 72},
- {9, 0x2a, 72},
- {23, 0x2a, 72},
- {40, 0x2b, 72},
- },
- /* 44 */
- {
- {3, 0x2a, 69},
- {6, 0x2a, 69},
- {10, 0x2a, 69},
- {15, 0x2a, 69},
- {24, 0x2a, 69},
- {31, 0x2a, 69},
- {41, 0x2a, 69},
- {56, 0x2b, 69},
- {3, 0x2a, 70},
- {6, 0x2a, 70},
- {10, 0x2a, 70},
- {15, 0x2a, 70},
- {24, 0x2a, 70},
- {31, 0x2a, 70},
- {41, 0x2a, 70},
- {56, 0x2b, 70},
- },
- /* 45 */
- {
- {3, 0x2a, 71},
- {6, 0x2a, 71},
- {10, 0x2a, 71},
- {15, 0x2a, 71},
- {24, 0x2a, 71},
- {31, 0x2a, 71},
- {41, 0x2a, 71},
- {56, 0x2b, 71},
- {3, 0x2a, 72},
- {6, 0x2a, 72},
- {10, 0x2a, 72},
- {15, 0x2a, 72},
- {24, 0x2a, 72},
- {31, 0x2a, 72},
- {41, 0x2a, 72},
- {56, 0x2b, 72},
- },
- /* 46 */
- {
- {2, 0x2a, 73},
- {9, 0x2a, 73},
- {23, 0x2a, 73},
- {40, 0x2b, 73},
- {2, 0x2a, 74},
- {9, 0x2a, 74},
- {23, 0x2a, 74},
- {40, 0x2b, 74},
- {2, 0x2a, 75},
- {9, 0x2a, 75},
- {23, 0x2a, 75},
- {40, 0x2b, 75},
- {2, 0x2a, 76},
- {9, 0x2a, 76},
- {23, 0x2a, 76},
- {40, 0x2b, 76},
- },
- /* 47 */
- {
- {3, 0x2a, 73},
- {6, 0x2a, 73},
- {10, 0x2a, 73},
- {15, 0x2a, 73},
- {24, 0x2a, 73},
- {31, 0x2a, 73},
- {41, 0x2a, 73},
- {56, 0x2b, 73},
- {3, 0x2a, 74},
- {6, 0x2a, 74},
- {10, 0x2a, 74},
- {15, 0x2a, 74},
- {24, 0x2a, 74},
- {31, 0x2a, 74},
- {41, 0x2a, 74},
- {56, 0x2b, 74},
- },
- /* 48 */
- {
- {3, 0x2a, 75},
- {6, 0x2a, 75},
- {10, 0x2a, 75},
- {15, 0x2a, 75},
- {24, 0x2a, 75},
- {31, 0x2a, 75},
- {41, 0x2a, 75},
- {56, 0x2b, 75},
- {3, 0x2a, 76},
- {6, 0x2a, 76},
- {10, 0x2a, 76},
- {15, 0x2a, 76},
- {24, 0x2a, 76},
- {31, 0x2a, 76},
- {41, 0x2a, 76},
- {56, 0x2b, 76},
- },
- /* 49 */
- {
- {1, 0x2a, 77},
- {22, 0x2b, 77},
- {1, 0x2a, 78},
- {22, 0x2b, 78},
- {1, 0x2a, 79},
- {22, 0x2b, 79},
- {1, 0x2a, 80},
- {22, 0x2b, 80},
- {1, 0x2a, 81},
- {22, 0x2b, 81},
- {1, 0x2a, 82},
- {22, 0x2b, 82},
- {1, 0x2a, 83},
- {22, 0x2b, 83},
- {1, 0x2a, 84},
- {22, 0x2b, 84},
- },
- /* 50 */
- {
- {2, 0x2a, 77},
- {9, 0x2a, 77},
- {23, 0x2a, 77},
- {40, 0x2b, 77},
- {2, 0x2a, 78},
- {9, 0x2a, 78},
- {23, 0x2a, 78},
- {40, 0x2b, 78},
- {2, 0x2a, 79},
- {9, 0x2a, 79},
- {23, 0x2a, 79},
- {40, 0x2b, 79},
- {2, 0x2a, 80},
- {9, 0x2a, 80},
- {23, 0x2a, 80},
- {40, 0x2b, 80},
- },
- /* 51 */
- {
- {3, 0x2a, 77},
- {6, 0x2a, 77},
- {10, 0x2a, 77},
- {15, 0x2a, 77},
- {24, 0x2a, 77},
- {31, 0x2a, 77},
- {41, 0x2a, 77},
- {56, 0x2b, 77},
- {3, 0x2a, 78},
- {6, 0x2a, 78},
- {10, 0x2a, 78},
- {15, 0x2a, 78},
- {24, 0x2a, 78},
- {31, 0x2a, 78},
- {41, 0x2a, 78},
- {56, 0x2b, 78},
- },
- /* 52 */
- {
- {3, 0x2a, 79},
- {6, 0x2a, 79},
- {10, 0x2a, 79},
- {15, 0x2a, 79},
- {24, 0x2a, 79},
- {31, 0x2a, 79},
- {41, 0x2a, 79},
- {56, 0x2b, 79},
- {3, 0x2a, 80},
- {6, 0x2a, 80},
- {10, 0x2a, 80},
- {15, 0x2a, 80},
- {24, 0x2a, 80},
- {31, 0x2a, 80},
- {41, 0x2a, 80},
- {56, 0x2b, 80},
- },
- /* 53 */
- {
- {2, 0x2a, 81},
- {9, 0x2a, 81},
- {23, 0x2a, 81},
- {40, 0x2b, 81},
- {2, 0x2a, 82},
- {9, 0x2a, 82},
- {23, 0x2a, 82},
- {40, 0x2b, 82},
- {2, 0x2a, 83},
- {9, 0x2a, 83},
- {23, 0x2a, 83},
- {40, 0x2b, 83},
- {2, 0x2a, 84},
- {9, 0x2a, 84},
- {23, 0x2a, 84},
- {40, 0x2b, 84},
- },
- /* 54 */
- {
- {3, 0x2a, 81},
- {6, 0x2a, 81},
- {10, 0x2a, 81},
- {15, 0x2a, 81},
- {24, 0x2a, 81},
- {31, 0x2a, 81},
- {41, 0x2a, 81},
- {56, 0x2b, 81},
- {3, 0x2a, 82},
- {6, 0x2a, 82},
- {10, 0x2a, 82},
- {15, 0x2a, 82},
- {24, 0x2a, 82},
- {31, 0x2a, 82},
- {41, 0x2a, 82},
- {56, 0x2b, 82},
- },
- /* 55 */
- {
- {3, 0x2a, 83},
- {6, 0x2a, 83},
- {10, 0x2a, 83},
- {15, 0x2a, 83},
- {24, 0x2a, 83},
- {31, 0x2a, 83},
- {41, 0x2a, 83},
- {56, 0x2b, 83},
- {3, 0x2a, 84},
- {6, 0x2a, 84},
- {10, 0x2a, 84},
- {15, 0x2a, 84},
- {24, 0x2a, 84},
- {31, 0x2a, 84},
- {41, 0x2a, 84},
- {56, 0x2b, 84},
- },
- /* 56 */
- {
- {0, 0x2b, 85},
- {0, 0x2b, 86},
- {0, 0x2b, 87},
- {0, 0x2b, 89},
- {0, 0x03, 106},
- {0, 0x03, 107},
- {0, 0x03, 113},
- {0, 0x03, 118},
- {0, 0x03, 119},
- {0, 0x03, 120},
- {0, 0x03, 121},
- {0, 0x03, 122},
- {70, 0x00, 0},
- {71, 0x00, 0},
- {73, 0x00, 0},
- {74, 0x01, 0},
- },
- /* 57 */
- {
- {1, 0x2a, 85},
- {22, 0x2b, 85},
- {1, 0x2a, 86},
- {22, 0x2b, 86},
- {1, 0x2a, 87},
- {22, 0x2b, 87},
- {1, 0x2a, 89},
- {22, 0x2b, 89},
- {1, 0x02, 106},
- {22, 0x03, 106},
- {1, 0x02, 107},
- {22, 0x03, 107},
- {1, 0x02, 113},
- {22, 0x03, 113},
- {1, 0x02, 118},
- {22, 0x03, 118},
- },
- /* 58 */
- {
- {2, 0x2a, 85},
- {9, 0x2a, 85},
- {23, 0x2a, 85},
- {40, 0x2b, 85},
- {2, 0x2a, 86},
- {9, 0x2a, 86},
- {23, 0x2a, 86},
- {40, 0x2b, 86},
- {2, 0x2a, 87},
- {9, 0x2a, 87},
- {23, 0x2a, 87},
- {40, 0x2b, 87},
- {2, 0x2a, 89},
- {9, 0x2a, 89},
- {23, 0x2a, 89},
- {40, 0x2b, 89},
- },
- /* 59 */
- {
- {3, 0x2a, 85},
- {6, 0x2a, 85},
- {10, 0x2a, 85},
- {15, 0x2a, 85},
- {24, 0x2a, 85},
- {31, 0x2a, 85},
- {41, 0x2a, 85},
- {56, 0x2b, 85},
- {3, 0x2a, 86},
- {6, 0x2a, 86},
- {10, 0x2a, 86},
- {15, 0x2a, 86},
- {24, 0x2a, 86},
- {31, 0x2a, 86},
- {41, 0x2a, 86},
- {56, 0x2b, 86},
- },
- /* 60 */
- {
- {3, 0x2a, 87},
- {6, 0x2a, 87},
- {10, 0x2a, 87},
- {15, 0x2a, 87},
- {24, 0x2a, 87},
- {31, 0x2a, 87},
- {41, 0x2a, 87},
- {56, 0x2b, 87},
- {3, 0x2a, 89},
- {6, 0x2a, 89},
- {10, 0x2a, 89},
- {15, 0x2a, 89},
- {24, 0x2a, 89},
- {31, 0x2a, 89},
- {41, 0x2a, 89},
- {56, 0x2b, 89},
- },
- /* 61 */
- {
- {2, 0x02, 106},
- {9, 0x02, 106},
- {23, 0x02, 106},
- {40, 0x03, 106},
- {2, 0x02, 107},
- {9, 0x02, 107},
- {23, 0x02, 107},
- {40, 0x03, 107},
- {2, 0x02, 113},
- {9, 0x02, 113},
- {23, 0x02, 113},
- {40, 0x03, 113},
- {2, 0x02, 118},
- {9, 0x02, 118},
- {23, 0x02, 118},
- {40, 0x03, 118},
- },
- /* 62 */
- {
- {3, 0x02, 106},
- {6, 0x02, 106},
- {10, 0x02, 106},
- {15, 0x02, 106},
- {24, 0x02, 106},
- {31, 0x02, 106},
- {41, 0x02, 106},
- {56, 0x03, 106},
- {3, 0x02, 107},
- {6, 0x02, 107},
- {10, 0x02, 107},
- {15, 0x02, 107},
- {24, 0x02, 107},
- {31, 0x02, 107},
- {41, 0x02, 107},
- {56, 0x03, 107},
- },
- /* 63 */
- {
- {3, 0x02, 113},
- {6, 0x02, 113},
- {10, 0x02, 113},
- {15, 0x02, 113},
- {24, 0x02, 113},
- {31, 0x02, 113},
- {41, 0x02, 113},
- {56, 0x03, 113},
- {3, 0x02, 118},
- {6, 0x02, 118},
- {10, 0x02, 118},
- {15, 0x02, 118},
- {24, 0x02, 118},
- {31, 0x02, 118},
- {41, 0x02, 118},
- {56, 0x03, 118},
- },
- /* 64 */
- {
- {1, 0x02, 119},
- {22, 0x03, 119},
- {1, 0x02, 120},
- {22, 0x03, 120},
- {1, 0x02, 121},
- {22, 0x03, 121},
- {1, 0x02, 122},
- {22, 0x03, 122},
- {0, 0x03, 38},
- {0, 0x03, 42},
- {0, 0x0b, 44},
- {0, 0x0b, 59},
- {0, 0x2b, 88},
- {0, 0x2b, 90},
- {75, 0x00, 0},
- {78, 0x00, 0},
- },
- /* 65 */
- {
- {2, 0x02, 119},
- {9, 0x02, 119},
- {23, 0x02, 119},
- {40, 0x03, 119},
- {2, 0x02, 120},
- {9, 0x02, 120},
- {23, 0x02, 120},
- {40, 0x03, 120},
- {2, 0x02, 121},
- {9, 0x02, 121},
- {23, 0x02, 121},
- {40, 0x03, 121},
- {2, 0x02, 122},
- {9, 0x02, 122},
- {23, 0x02, 122},
- {40, 0x03, 122},
- },
- /* 66 */
- {
- {3, 0x02, 119},
- {6, 0x02, 119},
- {10, 0x02, 119},
- {15, 0x02, 119},
- {24, 0x02, 119},
- {31, 0x02, 119},
- {41, 0x02, 119},
- {56, 0x03, 119},
- {3, 0x02, 120},
- {6, 0x02, 120},
- {10, 0x02, 120},
- {15, 0x02, 120},
- {24, 0x02, 120},
- {31, 0x02, 120},
- {41, 0x02, 120},
- {56, 0x03, 120},
- },
- /* 67 */
- {
- {3, 0x02, 121},
- {6, 0x02, 121},
- {10, 0x02, 121},
- {15, 0x02, 121},
- {24, 0x02, 121},
- {31, 0x02, 121},
- {41, 0x02, 121},
- {56, 0x03, 121},
- {3, 0x02, 122},
- {6, 0x02, 122},
- {10, 0x02, 122},
- {15, 0x02, 122},
- {24, 0x02, 122},
- {31, 0x02, 122},
- {41, 0x02, 122},
- {56, 0x03, 122},
- },
- /* 68 */
- {
- {1, 0x02, 38},
- {22, 0x03, 38},
- {1, 0x02, 42},
- {22, 0x03, 42},
- {1, 0x0a, 44},
- {22, 0x0b, 44},
- {1, 0x0a, 59},
- {22, 0x0b, 59},
- {1, 0x2a, 88},
- {22, 0x2b, 88},
- {1, 0x2a, 90},
- {22, 0x2b, 90},
- {76, 0x00, 0},
- {77, 0x00, 0},
- {79, 0x00, 0},
- {81, 0x00, 0},
- },
- /* 69 */
- {
- {2, 0x02, 38},
- {9, 0x02, 38},
- {23, 0x02, 38},
- {40, 0x03, 38},
- {2, 0x02, 42},
- {9, 0x02, 42},
- {23, 0x02, 42},
- {40, 0x03, 42},
- {2, 0x0a, 44},
- {9, 0x0a, 44},
- {23, 0x0a, 44},
- {40, 0x0b, 44},
- {2, 0x0a, 59},
- {9, 0x0a, 59},
- {23, 0x0a, 59},
- {40, 0x0b, 59},
- },
- /* 70 */
- {
- {3, 0x02, 38},
- {6, 0x02, 38},
- {10, 0x02, 38},
- {15, 0x02, 38},
- {24, 0x02, 38},
- {31, 0x02, 38},
- {41, 0x02, 38},
- {56, 0x03, 38},
- {3, 0x02, 42},
- {6, 0x02, 42},
- {10, 0x02, 42},
- {15, 0x02, 42},
- {24, 0x02, 42},
- {31, 0x02, 42},
- {41, 0x02, 42},
- {56, 0x03, 42},
- },
- /* 71 */
- {
- {3, 0x0a, 44},
- {6, 0x0a, 44},
- {10, 0x0a, 44},
- {15, 0x0a, 44},
- {24, 0x0a, 44},
- {31, 0x0a, 44},
- {41, 0x0a, 44},
- {56, 0x0b, 44},
- {3, 0x0a, 59},
- {6, 0x0a, 59},
- {10, 0x0a, 59},
- {15, 0x0a, 59},
- {24, 0x0a, 59},
- {31, 0x0a, 59},
- {41, 0x0a, 59},
- {56, 0x0b, 59},
- },
- /* 72 */
- {
- {2, 0x2a, 88},
- {9, 0x2a, 88},
- {23, 0x2a, 88},
- {40, 0x2b, 88},
- {2, 0x2a, 90},
- {9, 0x2a, 90},
- {23, 0x2a, 90},
- {40, 0x2b, 90},
- {0, 0x03, 33},
- {0, 0x0b, 34},
- {0, 0x0b, 40},
- {0, 0x0b, 41},
- {0, 0x0b, 63},
- {80, 0x00, 0},
- {82, 0x00, 0},
- {84, 0x00, 0},
- },
- /* 73 */
- {
- {3, 0x2a, 88},
- {6, 0x2a, 88},
- {10, 0x2a, 88},
- {15, 0x2a, 88},
- {24, 0x2a, 88},
- {31, 0x2a, 88},
- {41, 0x2a, 88},
- {56, 0x2b, 88},
- {3, 0x2a, 90},
- {6, 0x2a, 90},
- {10, 0x2a, 90},
- {15, 0x2a, 90},
- {24, 0x2a, 90},
- {31, 0x2a, 90},
- {41, 0x2a, 90},
- {56, 0x2b, 90},
- },
- /* 74 */
- {
- {1, 0x02, 33},
- {22, 0x03, 33},
- {1, 0x0a, 34},
- {22, 0x0b, 34},
- {1, 0x0a, 40},
- {22, 0x0b, 40},
- {1, 0x0a, 41},
- {22, 0x0b, 41},
- {1, 0x0a, 63},
- {22, 0x0b, 63},
- {0, 0x03, 39},
- {0, 0x03, 43},
- {0, 0x03, 124},
- {83, 0x00, 0},
- {85, 0x00, 0},
- {88, 0x00, 0},
- },
- /* 75 */
- {
- {2, 0x02, 33},
- {9, 0x02, 33},
- {23, 0x02, 33},
- {40, 0x03, 33},
- {2, 0x0a, 34},
- {9, 0x0a, 34},
- {23, 0x0a, 34},
- {40, 0x0b, 34},
- {2, 0x0a, 40},
- {9, 0x0a, 40},
- {23, 0x0a, 40},
- {40, 0x0b, 40},
- {2, 0x0a, 41},
- {9, 0x0a, 41},
- {23, 0x0a, 41},
- {40, 0x0b, 41},
- },
- /* 76 */
- {
- {3, 0x02, 33},
- {6, 0x02, 33},
- {10, 0x02, 33},
- {15, 0x02, 33},
- {24, 0x02, 33},
- {31, 0x02, 33},
- {41, 0x02, 33},
- {56, 0x03, 33},
- {3, 0x0a, 34},
- {6, 0x0a, 34},
- {10, 0x0a, 34},
- {15, 0x0a, 34},
- {24, 0x0a, 34},
- {31, 0x0a, 34},
- {41, 0x0a, 34},
- {56, 0x0b, 34},
- },
- /* 77 */
- {
- {3, 0x0a, 40},
- {6, 0x0a, 40},
- {10, 0x0a, 40},
- {15, 0x0a, 40},
- {24, 0x0a, 40},
- {31, 0x0a, 40},
- {41, 0x0a, 40},
- {56, 0x0b, 40},
- {3, 0x0a, 41},
- {6, 0x0a, 41},
- {10, 0x0a, 41},
- {15, 0x0a, 41},
- {24, 0x0a, 41},
- {31, 0x0a, 41},
- {41, 0x0a, 41},
- {56, 0x0b, 41},
- },
- /* 78 */
- {
- {2, 0x0a, 63},
- {9, 0x0a, 63},
- {23, 0x0a, 63},
- {40, 0x0b, 63},
- {1, 0x02, 39},
- {22, 0x03, 39},
- {1, 0x02, 43},
- {22, 0x03, 43},
- {1, 0x02, 124},
- {22, 0x03, 124},
- {0, 0x03, 35},
- {0, 0x0b, 62},
- {86, 0x00, 0},
- {87, 0x00, 0},
- {89, 0x00, 0},
- {90, 0x00, 0},
- },
- /* 79 */
- {
- {3, 0x0a, 63},
- {6, 0x0a, 63},
- {10, 0x0a, 63},
- {15, 0x0a, 63},
- {24, 0x0a, 63},
- {31, 0x0a, 63},
- {41, 0x0a, 63},
- {56, 0x0b, 63},
- {2, 0x02, 39},
- {9, 0x02, 39},
- {23, 0x02, 39},
- {40, 0x03, 39},
- {2, 0x02, 43},
- {9, 0x02, 43},
- {23, 0x02, 43},
- {40, 0x03, 43},
- },
- /* 80 */
- {
- {3, 0x02, 39},
- {6, 0x02, 39},
- {10, 0x02, 39},
- {15, 0x02, 39},
- {24, 0x02, 39},
- {31, 0x02, 39},
- {41, 0x02, 39},
- {56, 0x03, 39},
- {3, 0x02, 43},
- {6, 0x02, 43},
- {10, 0x02, 43},
- {15, 0x02, 43},
- {24, 0x02, 43},
- {31, 0x02, 43},
- {41, 0x02, 43},
- {56, 0x03, 43},
- },
- /* 81 */
- {
- {2, 0x02, 124},
- {9, 0x02, 124},
- {23, 0x02, 124},
- {40, 0x03, 124},
- {1, 0x02, 35},
- {22, 0x03, 35},
- {1, 0x0a, 62},
- {22, 0x0b, 62},
- {0, 0x1b, 0},
- {0, 0x03, 36},
- {0, 0x0b, 64},
- {0, 0x0b, 91},
- {0, 0x0b, 93},
- {0, 0x03, 126},
- {91, 0x00, 0},
- {92, 0x00, 0},
- },
- /* 82 */
- {
- {3, 0x02, 124},
- {6, 0x02, 124},
- {10, 0x02, 124},
- {15, 0x02, 124},
- {24, 0x02, 124},
- {31, 0x02, 124},
- {41, 0x02, 124},
- {56, 0x03, 124},
- {2, 0x02, 35},
- {9, 0x02, 35},
- {23, 0x02, 35},
- {40, 0x03, 35},
- {2, 0x0a, 62},
- {9, 0x0a, 62},
- {23, 0x0a, 62},
- {40, 0x0b, 62},
- },
- /* 83 */
- {
- {3, 0x02, 35},
- {6, 0x02, 35},
- {10, 0x02, 35},
- {15, 0x02, 35},
- {24, 0x02, 35},
- {31, 0x02, 35},
- {41, 0x02, 35},
- {56, 0x03, 35},
- {3, 0x0a, 62},
- {6, 0x0a, 62},
- {10, 0x0a, 62},
- {15, 0x0a, 62},
- {24, 0x0a, 62},
- {31, 0x0a, 62},
- {41, 0x0a, 62},
- {56, 0x0b, 62},
- },
- /* 84 */
- {
- {1, 0x1a, 0},
- {22, 0x1b, 0},
- {1, 0x02, 36},
- {22, 0x03, 36},
- {1, 0x0a, 64},
- {22, 0x0b, 64},
- {1, 0x0a, 91},
- {22, 0x0b, 91},
- {1, 0x0a, 93},
- {22, 0x0b, 93},
- {1, 0x02, 126},
- {22, 0x03, 126},
- {0, 0x03, 94},
- {0, 0x0b, 125},
- {93, 0x00, 0},
- {94, 0x00, 0},
- },
- /* 85 */
- {
- {2, 0x1a, 0},
- {9, 0x1a, 0},
- {23, 0x1a, 0},
- {40, 0x1b, 0},
- {2, 0x02, 36},
- {9, 0x02, 36},
- {23, 0x02, 36},
- {40, 0x03, 36},
- {2, 0x0a, 64},
- {9, 0x0a, 64},
- {23, 0x0a, 64},
- {40, 0x0b, 64},
- {2, 0x0a, 91},
- {9, 0x0a, 91},
- {23, 0x0a, 91},
- {40, 0x0b, 91},
- },
- /* 86 */
- {
- {3, 0x1a, 0},
- {6, 0x1a, 0},
- {10, 0x1a, 0},
- {15, 0x1a, 0},
- {24, 0x1a, 0},
- {31, 0x1a, 0},
- {41, 0x1a, 0},
- {56, 0x1b, 0},
- {3, 0x02, 36},
- {6, 0x02, 36},
- {10, 0x02, 36},
- {15, 0x02, 36},
- {24, 0x02, 36},
- {31, 0x02, 36},
- {41, 0x02, 36},
- {56, 0x03, 36},
- },
- /* 87 */
- {
- {3, 0x0a, 64},
- {6, 0x0a, 64},
- {10, 0x0a, 64},
- {15, 0x0a, 64},
- {24, 0x0a, 64},
- {31, 0x0a, 64},
- {41, 0x0a, 64},
- {56, 0x0b, 64},
- {3, 0x0a, 91},
- {6, 0x0a, 91},
- {10, 0x0a, 91},
- {15, 0x0a, 91},
- {24, 0x0a, 91},
- {31, 0x0a, 91},
- {41, 0x0a, 91},
- {56, 0x0b, 91},
- },
- /* 88 */
- {
- {2, 0x0a, 93},
- {9, 0x0a, 93},
- {23, 0x0a, 93},
- {40, 0x0b, 93},
- {2, 0x02, 126},
- {9, 0x02, 126},
- {23, 0x02, 126},
- {40, 0x03, 126},
- {1, 0x02, 94},
- {22, 0x03, 94},
- {1, 0x0a, 125},
- {22, 0x0b, 125},
- {0, 0x0b, 60},
- {0, 0x03, 96},
- {0, 0x0b, 123},
- {95, 0x00, 0},
- },
- /* 89 */
- {
- {3, 0x0a, 93},
- {6, 0x0a, 93},
- {10, 0x0a, 93},
- {15, 0x0a, 93},
- {24, 0x0a, 93},
- {31, 0x0a, 93},
- {41, 0x0a, 93},
- {56, 0x0b, 93},
- {3, 0x02, 126},
- {6, 0x02, 126},
- {10, 0x02, 126},
- {15, 0x02, 126},
- {24, 0x02, 126},
- {31, 0x02, 126},
- {41, 0x02, 126},
- {56, 0x03, 126},
- },
- /* 90 */
- {
- {2, 0x02, 94},
- {9, 0x02, 94},
- {23, 0x02, 94},
- {40, 0x03, 94},
- {2, 0x0a, 125},
- {9, 0x0a, 125},
- {23, 0x0a, 125},
- {40, 0x0b, 125},
- {1, 0x0a, 60},
- {22, 0x0b, 60},
- {1, 0x02, 96},
- {22, 0x03, 96},
- {1, 0x0a, 123},
- {22, 0x0b, 123},
- {96, 0x00, 0},
- {110, 0x00, 0},
- },
- /* 91 */
- {
- {3, 0x02, 94},
- {6, 0x02, 94},
- {10, 0x02, 94},
- {15, 0x02, 94},
- {24, 0x02, 94},
- {31, 0x02, 94},
- {41, 0x02, 94},
- {56, 0x03, 94},
- {3, 0x0a, 125},
- {6, 0x0a, 125},
- {10, 0x0a, 125},
- {15, 0x0a, 125},
- {24, 0x0a, 125},
- {31, 0x0a, 125},
- {41, 0x0a, 125},
- {56, 0x0b, 125},
- },
- /* 92 */
- {
- {2, 0x0a, 60},
- {9, 0x0a, 60},
- {23, 0x0a, 60},
- {40, 0x0b, 60},
- {2, 0x02, 96},
- {9, 0x02, 96},
- {23, 0x02, 96},
- {40, 0x03, 96},
- {2, 0x0a, 123},
- {9, 0x0a, 123},
- {23, 0x0a, 123},
- {40, 0x0b, 123},
- {97, 0x00, 0},
- {101, 0x00, 0},
- {111, 0x00, 0},
- {133, 0x00, 0},
- },
- /* 93 */
- {
- {3, 0x0a, 60},
- {6, 0x0a, 60},
- {10, 0x0a, 60},
- {15, 0x0a, 60},
- {24, 0x0a, 60},
- {31, 0x0a, 60},
- {41, 0x0a, 60},
- {56, 0x0b, 60},
- {3, 0x02, 96},
- {6, 0x02, 96},
- {10, 0x02, 96},
- {15, 0x02, 96},
- {24, 0x02, 96},
- {31, 0x02, 96},
- {41, 0x02, 96},
- {56, 0x03, 96},
- },
- /* 94 */
- {
- {3, 0x0a, 123},
- {6, 0x0a, 123},
- {10, 0x0a, 123},
- {15, 0x0a, 123},
- {24, 0x0a, 123},
- {31, 0x0a, 123},
- {41, 0x0a, 123},
- {56, 0x0b, 123},
- {98, 0x00, 0},
- {99, 0x00, 0},
- {102, 0x00, 0},
- {105, 0x00, 0},
- {112, 0x00, 0},
- {119, 0x00, 0},
- {134, 0x00, 0},
- {153, 0x00, 0},
- },
- /* 95 */
- {
- {0, 0x0b, 92},
- {0, 0x0b, 195},
- {0, 0x0b, 208},
- {100, 0x00, 0},
- {103, 0x00, 0},
- {104, 0x00, 0},
- {106, 0x00, 0},
- {107, 0x00, 0},
- {113, 0x00, 0},
- {116, 0x00, 0},
- {120, 0x00, 0},
- {126, 0x00, 0},
- {135, 0x00, 0},
- {142, 0x00, 0},
- {154, 0x00, 0},
- {169, 0x00, 0},
- },
- /* 96 */
- {
- {1, 0x0a, 92},
- {22, 0x0b, 92},
- {1, 0x0a, 195},
- {22, 0x0b, 195},
- {1, 0x0a, 208},
- {22, 0x0b, 208},
- {0, 0x0b, 128},
- {0, 0x0b, 130},
- {0, 0x0b, 131},
- {0, 0x0b, 162},
- {0, 0x0b, 184},
- {0, 0x0b, 194},
- {0, 0x0b, 224},
- {0, 0x0b, 226},
- {108, 0x00, 0},
- {109, 0x00, 0},
- },
- /* 97 */
- {
- {2, 0x0a, 92},
- {9, 0x0a, 92},
- {23, 0x0a, 92},
- {40, 0x0b, 92},
- {2, 0x0a, 195},
- {9, 0x0a, 195},
- {23, 0x0a, 195},
- {40, 0x0b, 195},
- {2, 0x0a, 208},
- {9, 0x0a, 208},
- {23, 0x0a, 208},
- {40, 0x0b, 208},
- {1, 0x0a, 128},
- {22, 0x0b, 128},
- {1, 0x0a, 130},
- {22, 0x0b, 130},
- },
- /* 98 */
- {
- {3, 0x0a, 92},
- {6, 0x0a, 92},
- {10, 0x0a, 92},
- {15, 0x0a, 92},
- {24, 0x0a, 92},
- {31, 0x0a, 92},
- {41, 0x0a, 92},
- {56, 0x0b, 92},
- {3, 0x0a, 195},
- {6, 0x0a, 195},
- {10, 0x0a, 195},
- {15, 0x0a, 195},
- {24, 0x0a, 195},
- {31, 0x0a, 195},
- {41, 0x0a, 195},
- {56, 0x0b, 195},
- },
- /* 99 */
- {
- {3, 0x0a, 208},
- {6, 0x0a, 208},
- {10, 0x0a, 208},
- {15, 0x0a, 208},
- {24, 0x0a, 208},
- {31, 0x0a, 208},
- {41, 0x0a, 208},
- {56, 0x0b, 208},
- {2, 0x0a, 128},
- {9, 0x0a, 128},
- {23, 0x0a, 128},
- {40, 0x0b, 128},
- {2, 0x0a, 130},
- {9, 0x0a, 130},
- {23, 0x0a, 130},
- {40, 0x0b, 130},
- },
- /* 100 */
- {
- {3, 0x0a, 128},
- {6, 0x0a, 128},
- {10, 0x0a, 128},
- {15, 0x0a, 128},
- {24, 0x0a, 128},
- {31, 0x0a, 128},
- {41, 0x0a, 128},
- {56, 0x0b, 128},
- {3, 0x0a, 130},
- {6, 0x0a, 130},
- {10, 0x0a, 130},
- {15, 0x0a, 130},
- {24, 0x0a, 130},
- {31, 0x0a, 130},
- {41, 0x0a, 130},
- {56, 0x0b, 130},
- },
- /* 101 */
- {
- {1, 0x0a, 131},
- {22, 0x0b, 131},
- {1, 0x0a, 162},
- {22, 0x0b, 162},
- {1, 0x0a, 184},
- {22, 0x0b, 184},
- {1, 0x0a, 194},
- {22, 0x0b, 194},
- {1, 0x0a, 224},
- {22, 0x0b, 224},
- {1, 0x0a, 226},
- {22, 0x0b, 226},
- {0, 0x0b, 153},
- {0, 0x0b, 161},
- {0, 0x0b, 167},
- {0, 0x0b, 172},
- },
- /* 102 */
- {
- {2, 0x0a, 131},
- {9, 0x0a, 131},
- {23, 0x0a, 131},
- {40, 0x0b, 131},
- {2, 0x0a, 162},
- {9, 0x0a, 162},
- {23, 0x0a, 162},
- {40, 0x0b, 162},
- {2, 0x0a, 184},
- {9, 0x0a, 184},
- {23, 0x0a, 184},
- {40, 0x0b, 184},
- {2, 0x0a, 194},
- {9, 0x0a, 194},
- {23, 0x0a, 194},
- {40, 0x0b, 194},
- },
- /* 103 */
- {
- {3, 0x0a, 131},
- {6, 0x0a, 131},
- {10, 0x0a, 131},
- {15, 0x0a, 131},
- {24, 0x0a, 131},
- {31, 0x0a, 131},
- {41, 0x0a, 131},
- {56, 0x0b, 131},
- {3, 0x0a, 162},
- {6, 0x0a, 162},
- {10, 0x0a, 162},
- {15, 0x0a, 162},
- {24, 0x0a, 162},
- {31, 0x0a, 162},
- {41, 0x0a, 162},
- {56, 0x0b, 162},
- },
- /* 104 */
- {
- {3, 0x0a, 184},
- {6, 0x0a, 184},
- {10, 0x0a, 184},
- {15, 0x0a, 184},
- {24, 0x0a, 184},
- {31, 0x0a, 184},
- {41, 0x0a, 184},
- {56, 0x0b, 184},
- {3, 0x0a, 194},
- {6, 0x0a, 194},
- {10, 0x0a, 194},
- {15, 0x0a, 194},
- {24, 0x0a, 194},
- {31, 0x0a, 194},
- {41, 0x0a, 194},
- {56, 0x0b, 194},
- },
- /* 105 */
- {
- {2, 0x0a, 224},
- {9, 0x0a, 224},
- {23, 0x0a, 224},
- {40, 0x0b, 224},
- {2, 0x0a, 226},
- {9, 0x0a, 226},
- {23, 0x0a, 226},
- {40, 0x0b, 226},
- {1, 0x0a, 153},
- {22, 0x0b, 153},
- {1, 0x0a, 161},
- {22, 0x0b, 161},
- {1, 0x0a, 167},
- {22, 0x0b, 167},
- {1, 0x0a, 172},
- {22, 0x0b, 172},
- },
- /* 106 */
- {
- {3, 0x0a, 224},
- {6, 0x0a, 224},
- {10, 0x0a, 224},
- {15, 0x0a, 224},
- {24, 0x0a, 224},
- {31, 0x0a, 224},
- {41, 0x0a, 224},
- {56, 0x0b, 224},
- {3, 0x0a, 226},
- {6, 0x0a, 226},
- {10, 0x0a, 226},
- {15, 0x0a, 226},
- {24, 0x0a, 226},
- {31, 0x0a, 226},
- {41, 0x0a, 226},
- {56, 0x0b, 226},
- },
- /* 107 */
- {
- {2, 0x0a, 153},
- {9, 0x0a, 153},
- {23, 0x0a, 153},
- {40, 0x0b, 153},
- {2, 0x0a, 161},
- {9, 0x0a, 161},
- {23, 0x0a, 161},
- {40, 0x0b, 161},
- {2, 0x0a, 167},
- {9, 0x0a, 167},
- {23, 0x0a, 167},
- {40, 0x0b, 167},
- {2, 0x0a, 172},
- {9, 0x0a, 172},
- {23, 0x0a, 172},
- {40, 0x0b, 172},
- },
- /* 108 */
- {
- {3, 0x0a, 153},
- {6, 0x0a, 153},
- {10, 0x0a, 153},
- {15, 0x0a, 153},
- {24, 0x0a, 153},
- {31, 0x0a, 153},
- {41, 0x0a, 153},
- {56, 0x0b, 153},
- {3, 0x0a, 161},
- {6, 0x0a, 161},
- {10, 0x0a, 161},
- {15, 0x0a, 161},
- {24, 0x0a, 161},
- {31, 0x0a, 161},
- {41, 0x0a, 161},
- {56, 0x0b, 161},
- },
- /* 109 */
- {
- {3, 0x0a, 167},
- {6, 0x0a, 167},
- {10, 0x0a, 167},
- {15, 0x0a, 167},
- {24, 0x0a, 167},
- {31, 0x0a, 167},
- {41, 0x0a, 167},
- {56, 0x0b, 167},
- {3, 0x0a, 172},
- {6, 0x0a, 172},
- {10, 0x0a, 172},
- {15, 0x0a, 172},
- {24, 0x0a, 172},
- {31, 0x0a, 172},
- {41, 0x0a, 172},
- {56, 0x0b, 172},
- },
- /* 110 */
- {
- {114, 0x00, 0},
- {115, 0x00, 0},
- {117, 0x00, 0},
- {118, 0x00, 0},
- {121, 0x00, 0},
- {123, 0x00, 0},
- {127, 0x00, 0},
- {130, 0x00, 0},
- {136, 0x00, 0},
- {139, 0x00, 0},
- {143, 0x00, 0},
- {146, 0x00, 0},
- {155, 0x00, 0},
- {162, 0x00, 0},
- {170, 0x00, 0},
- {180, 0x00, 0},
- },
- /* 111 */
- {
- {0, 0x0b, 176},
- {0, 0x0b, 177},
- {0, 0x0b, 179},
- {0, 0x0b, 209},
- {0, 0x0b, 216},
- {0, 0x0b, 217},
- {0, 0x0b, 227},
- {0, 0x0b, 229},
- {0, 0x0b, 230},
- {122, 0x00, 0},
- {124, 0x00, 0},
- {125, 0x00, 0},
- {128, 0x00, 0},
- {129, 0x00, 0},
- {131, 0x00, 0},
- {132, 0x00, 0},
- },
- /* 112 */
- {
- {1, 0x0a, 176},
- {22, 0x0b, 176},
- {1, 0x0a, 177},
- {22, 0x0b, 177},
- {1, 0x0a, 179},
- {22, 0x0b, 179},
- {1, 0x0a, 209},
- {22, 0x0b, 209},
- {1, 0x0a, 216},
- {22, 0x0b, 216},
- {1, 0x0a, 217},
- {22, 0x0b, 217},
- {1, 0x0a, 227},
- {22, 0x0b, 227},
- {1, 0x0a, 229},
- {22, 0x0b, 229},
- },
- /* 113 */
- {
- {2, 0x0a, 176},
- {9, 0x0a, 176},
- {23, 0x0a, 176},
- {40, 0x0b, 176},
- {2, 0x0a, 177},
- {9, 0x0a, 177},
- {23, 0x0a, 177},
- {40, 0x0b, 177},
- {2, 0x0a, 179},
- {9, 0x0a, 179},
- {23, 0x0a, 179},
- {40, 0x0b, 179},
- {2, 0x0a, 209},
- {9, 0x0a, 209},
- {23, 0x0a, 209},
- {40, 0x0b, 209},
- },
- /* 114 */
- {
- {3, 0x0a, 176},
- {6, 0x0a, 176},
- {10, 0x0a, 176},
- {15, 0x0a, 176},
- {24, 0x0a, 176},
- {31, 0x0a, 176},
- {41, 0x0a, 176},
- {56, 0x0b, 176},
- {3, 0x0a, 177},
- {6, 0x0a, 177},
- {10, 0x0a, 177},
- {15, 0x0a, 177},
- {24, 0x0a, 177},
- {31, 0x0a, 177},
- {41, 0x0a, 177},
- {56, 0x0b, 177},
- },
- /* 115 */
- {
- {3, 0x0a, 179},
- {6, 0x0a, 179},
- {10, 0x0a, 179},
- {15, 0x0a, 179},
- {24, 0x0a, 179},
- {31, 0x0a, 179},
- {41, 0x0a, 179},
- {56, 0x0b, 179},
- {3, 0x0a, 209},
- {6, 0x0a, 209},
- {10, 0x0a, 209},
- {15, 0x0a, 209},
- {24, 0x0a, 209},
- {31, 0x0a, 209},
- {41, 0x0a, 209},
- {56, 0x0b, 209},
- },
- /* 116 */
- {
- {2, 0x0a, 216},
- {9, 0x0a, 216},
- {23, 0x0a, 216},
- {40, 0x0b, 216},
- {2, 0x0a, 217},
- {9, 0x0a, 217},
- {23, 0x0a, 217},
- {40, 0x0b, 217},
- {2, 0x0a, 227},
- {9, 0x0a, 227},
- {23, 0x0a, 227},
- {40, 0x0b, 227},
- {2, 0x0a, 229},
- {9, 0x0a, 229},
- {23, 0x0a, 229},
- {40, 0x0b, 229},
- },
- /* 117 */
- {
- {3, 0x0a, 216},
- {6, 0x0a, 216},
- {10, 0x0a, 216},
- {15, 0x0a, 216},
- {24, 0x0a, 216},
- {31, 0x0a, 216},
- {41, 0x0a, 216},
- {56, 0x0b, 216},
- {3, 0x0a, 217},
- {6, 0x0a, 217},
- {10, 0x0a, 217},
- {15, 0x0a, 217},
- {24, 0x0a, 217},
- {31, 0x0a, 217},
- {41, 0x0a, 217},
- {56, 0x0b, 217},
- },
- /* 118 */
- {
- {3, 0x0a, 227},
- {6, 0x0a, 227},
- {10, 0x0a, 227},
- {15, 0x0a, 227},
- {24, 0x0a, 227},
- {31, 0x0a, 227},
- {41, 0x0a, 227},
- {56, 0x0b, 227},
- {3, 0x0a, 229},
- {6, 0x0a, 229},
- {10, 0x0a, 229},
- {15, 0x0a, 229},
- {24, 0x0a, 229},
- {31, 0x0a, 229},
- {41, 0x0a, 229},
- {56, 0x0b, 229},
- },
- /* 119 */
- {
- {1, 0x0a, 230},
- {22, 0x0b, 230},
- {0, 0x0b, 129},
- {0, 0x0b, 132},
- {0, 0x0b, 133},
- {0, 0x0b, 134},
- {0, 0x0b, 136},
- {0, 0x0b, 146},
- {0, 0x0b, 154},
- {0, 0x0b, 156},
- {0, 0x0b, 160},
- {0, 0x0b, 163},
- {0, 0x0b, 164},
- {0, 0x0b, 169},
- {0, 0x0b, 170},
- {0, 0x0b, 173},
- },
- /* 120 */
- {
- {2, 0x0a, 230},
- {9, 0x0a, 230},
- {23, 0x0a, 230},
- {40, 0x0b, 230},
- {1, 0x0a, 129},
- {22, 0x0b, 129},
- {1, 0x0a, 132},
- {22, 0x0b, 132},
- {1, 0x0a, 133},
- {22, 0x0b, 133},
- {1, 0x0a, 134},
- {22, 0x0b, 134},
- {1, 0x0a, 136},
- {22, 0x0b, 136},
- {1, 0x0a, 146},
- {22, 0x0b, 146},
- },
- /* 121 */
- {
- {3, 0x0a, 230},
- {6, 0x0a, 230},
- {10, 0x0a, 230},
- {15, 0x0a, 230},
- {24, 0x0a, 230},
- {31, 0x0a, 230},
- {41, 0x0a, 230},
- {56, 0x0b, 230},
- {2, 0x0a, 129},
- {9, 0x0a, 129},
- {23, 0x0a, 129},
- {40, 0x0b, 129},
- {2, 0x0a, 132},
- {9, 0x0a, 132},
- {23, 0x0a, 132},
- {40, 0x0b, 132},
- },
- /* 122 */
- {
- {3, 0x0a, 129},
- {6, 0x0a, 129},
- {10, 0x0a, 129},
- {15, 0x0a, 129},
- {24, 0x0a, 129},
- {31, 0x0a, 129},
- {41, 0x0a, 129},
- {56, 0x0b, 129},
- {3, 0x0a, 132},
- {6, 0x0a, 132},
- {10, 0x0a, 132},
- {15, 0x0a, 132},
- {24, 0x0a, 132},
- {31, 0x0a, 132},
- {41, 0x0a, 132},
- {56, 0x0b, 132},
- },
- /* 123 */
- {
- {2, 0x0a, 133},
- {9, 0x0a, 133},
- {23, 0x0a, 133},
- {40, 0x0b, 133},
- {2, 0x0a, 134},
- {9, 0x0a, 134},
- {23, 0x0a, 134},
- {40, 0x0b, 134},
- {2, 0x0a, 136},
- {9, 0x0a, 136},
- {23, 0x0a, 136},
- {40, 0x0b, 136},
- {2, 0x0a, 146},
- {9, 0x0a, 146},
- {23, 0x0a, 146},
- {40, 0x0b, 146},
- },
- /* 124 */
- {
- {3, 0x0a, 133},
- {6, 0x0a, 133},
- {10, 0x0a, 133},
- {15, 0x0a, 133},
- {24, 0x0a, 133},
- {31, 0x0a, 133},
- {41, 0x0a, 133},
- {56, 0x0b, 133},
- {3, 0x0a, 134},
- {6, 0x0a, 134},
- {10, 0x0a, 134},
- {15, 0x0a, 134},
- {24, 0x0a, 134},
- {31, 0x0a, 134},
- {41, 0x0a, 134},
- {56, 0x0b, 134},
- },
- /* 125 */
- {
- {3, 0x0a, 136},
- {6, 0x0a, 136},
- {10, 0x0a, 136},
- {15, 0x0a, 136},
- {24, 0x0a, 136},
- {31, 0x0a, 136},
- {41, 0x0a, 136},
- {56, 0x0b, 136},
- {3, 0x0a, 146},
- {6, 0x0a, 146},
- {10, 0x0a, 146},
- {15, 0x0a, 146},
- {24, 0x0a, 146},
- {31, 0x0a, 146},
- {41, 0x0a, 146},
- {56, 0x0b, 146},
- },
- /* 126 */
- {
- {1, 0x0a, 154},
- {22, 0x0b, 154},
- {1, 0x0a, 156},
- {22, 0x0b, 156},
- {1, 0x0a, 160},
- {22, 0x0b, 160},
- {1, 0x0a, 163},
- {22, 0x0b, 163},
- {1, 0x0a, 164},
- {22, 0x0b, 164},
- {1, 0x0a, 169},
- {22, 0x0b, 169},
- {1, 0x0a, 170},
- {22, 0x0b, 170},
- {1, 0x0a, 173},
- {22, 0x0b, 173},
- },
- /* 127 */
- {
- {2, 0x0a, 154},
- {9, 0x0a, 154},
- {23, 0x0a, 154},
- {40, 0x0b, 154},
- {2, 0x0a, 156},
- {9, 0x0a, 156},
- {23, 0x0a, 156},
- {40, 0x0b, 156},
- {2, 0x0a, 160},
- {9, 0x0a, 160},
- {23, 0x0a, 160},
- {40, 0x0b, 160},
- {2, 0x0a, 163},
- {9, 0x0a, 163},
- {23, 0x0a, 163},
- {40, 0x0b, 163},
- },
- /* 128 */
- {
- {3, 0x0a, 154},
- {6, 0x0a, 154},
- {10, 0x0a, 154},
- {15, 0x0a, 154},
- {24, 0x0a, 154},
- {31, 0x0a, 154},
- {41, 0x0a, 154},
- {56, 0x0b, 154},
- {3, 0x0a, 156},
- {6, 0x0a, 156},
- {10, 0x0a, 156},
- {15, 0x0a, 156},
- {24, 0x0a, 156},
- {31, 0x0a, 156},
- {41, 0x0a, 156},
- {56, 0x0b, 156},
- },
- /* 129 */
- {
- {3, 0x0a, 160},
- {6, 0x0a, 160},
- {10, 0x0a, 160},
- {15, 0x0a, 160},
- {24, 0x0a, 160},
- {31, 0x0a, 160},
- {41, 0x0a, 160},
- {56, 0x0b, 160},
- {3, 0x0a, 163},
- {6, 0x0a, 163},
- {10, 0x0a, 163},
- {15, 0x0a, 163},
- {24, 0x0a, 163},
- {31, 0x0a, 163},
- {41, 0x0a, 163},
- {56, 0x0b, 163},
- },
- /* 130 */
- {
- {2, 0x0a, 164},
- {9, 0x0a, 164},
- {23, 0x0a, 164},
- {40, 0x0b, 164},
- {2, 0x0a, 169},
- {9, 0x0a, 169},
- {23, 0x0a, 169},
- {40, 0x0b, 169},
- {2, 0x0a, 170},
- {9, 0x0a, 170},
- {23, 0x0a, 170},
- {40, 0x0b, 170},
- {2, 0x0a, 173},
- {9, 0x0a, 173},
- {23, 0x0a, 173},
- {40, 0x0b, 173},
- },
- /* 131 */
- {
- {3, 0x0a, 164},
- {6, 0x0a, 164},
- {10, 0x0a, 164},
- {15, 0x0a, 164},
- {24, 0x0a, 164},
- {31, 0x0a, 164},
- {41, 0x0a, 164},
- {56, 0x0b, 164},
- {3, 0x0a, 169},
- {6, 0x0a, 169},
- {10, 0x0a, 169},
- {15, 0x0a, 169},
- {24, 0x0a, 169},
- {31, 0x0a, 169},
- {41, 0x0a, 169},
- {56, 0x0b, 169},
- },
- /* 132 */
- {
- {3, 0x0a, 170},
- {6, 0x0a, 170},
- {10, 0x0a, 170},
- {15, 0x0a, 170},
- {24, 0x0a, 170},
- {31, 0x0a, 170},
- {41, 0x0a, 170},
- {56, 0x0b, 170},
- {3, 0x0a, 173},
- {6, 0x0a, 173},
- {10, 0x0a, 173},
- {15, 0x0a, 173},
- {24, 0x0a, 173},
- {31, 0x0a, 173},
- {41, 0x0a, 173},
- {56, 0x0b, 173},
- },
- /* 133 */
- {
- {137, 0x00, 0},
- {138, 0x00, 0},
- {140, 0x00, 0},
- {141, 0x00, 0},
- {144, 0x00, 0},
- {145, 0x00, 0},
- {147, 0x00, 0},
- {150, 0x00, 0},
- {156, 0x00, 0},
- {159, 0x00, 0},
- {163, 0x00, 0},
- {166, 0x00, 0},
- {171, 0x00, 0},
- {174, 0x00, 0},
- {181, 0x00, 0},
- {190, 0x00, 0},
- },
- /* 134 */
- {
- {0, 0x0b, 178},
- {0, 0x0b, 181},
- {0, 0x0b, 185},
- {0, 0x0b, 186},
- {0, 0x0b, 187},
- {0, 0x0b, 189},
- {0, 0x0b, 190},
- {0, 0x0b, 196},
- {0, 0x0b, 198},
- {0, 0x0b, 228},
- {0, 0x0b, 232},
- {0, 0x0b, 233},
- {148, 0x00, 0},
- {149, 0x00, 0},
- {151, 0x00, 0},
- {152, 0x00, 0},
- },
- /* 135 */
- {
- {1, 0x0a, 178},
- {22, 0x0b, 178},
- {1, 0x0a, 181},
- {22, 0x0b, 181},
- {1, 0x0a, 185},
- {22, 0x0b, 185},
- {1, 0x0a, 186},
- {22, 0x0b, 186},
- {1, 0x0a, 187},
- {22, 0x0b, 187},
- {1, 0x0a, 189},
- {22, 0x0b, 189},
- {1, 0x0a, 190},
- {22, 0x0b, 190},
- {1, 0x0a, 196},
- {22, 0x0b, 196},
- },
- /* 136 */
- {
- {2, 0x0a, 178},
- {9, 0x0a, 178},
- {23, 0x0a, 178},
- {40, 0x0b, 178},
- {2, 0x0a, 181},
- {9, 0x0a, 181},
- {23, 0x0a, 181},
- {40, 0x0b, 181},
- {2, 0x0a, 185},
- {9, 0x0a, 185},
- {23, 0x0a, 185},
- {40, 0x0b, 185},
- {2, 0x0a, 186},
- {9, 0x0a, 186},
- {23, 0x0a, 186},
- {40, 0x0b, 186},
- },
- /* 137 */
- {
- {3, 0x0a, 178},
- {6, 0x0a, 178},
- {10, 0x0a, 178},
- {15, 0x0a, 178},
- {24, 0x0a, 178},
- {31, 0x0a, 178},
- {41, 0x0a, 178},
- {56, 0x0b, 178},
- {3, 0x0a, 181},
- {6, 0x0a, 181},
- {10, 0x0a, 181},
- {15, 0x0a, 181},
- {24, 0x0a, 181},
- {31, 0x0a, 181},
- {41, 0x0a, 181},
- {56, 0x0b, 181},
- },
- /* 138 */
- {
- {3, 0x0a, 185},
- {6, 0x0a, 185},
- {10, 0x0a, 185},
- {15, 0x0a, 185},
- {24, 0x0a, 185},
- {31, 0x0a, 185},
- {41, 0x0a, 185},
- {56, 0x0b, 185},
- {3, 0x0a, 186},
- {6, 0x0a, 186},
- {10, 0x0a, 186},
- {15, 0x0a, 186},
- {24, 0x0a, 186},
- {31, 0x0a, 186},
- {41, 0x0a, 186},
- {56, 0x0b, 186},
- },
- /* 139 */
- {
- {2, 0x0a, 187},
- {9, 0x0a, 187},
- {23, 0x0a, 187},
- {40, 0x0b, 187},
- {2, 0x0a, 189},
- {9, 0x0a, 189},
- {23, 0x0a, 189},
- {40, 0x0b, 189},
- {2, 0x0a, 190},
- {9, 0x0a, 190},
- {23, 0x0a, 190},
- {40, 0x0b, 190},
- {2, 0x0a, 196},
- {9, 0x0a, 196},
- {23, 0x0a, 196},
- {40, 0x0b, 196},
- },
- /* 140 */
- {
- {3, 0x0a, 187},
- {6, 0x0a, 187},
- {10, 0x0a, 187},
- {15, 0x0a, 187},
- {24, 0x0a, 187},
- {31, 0x0a, 187},
- {41, 0x0a, 187},
- {56, 0x0b, 187},
- {3, 0x0a, 189},
- {6, 0x0a, 189},
- {10, 0x0a, 189},
- {15, 0x0a, 189},
- {24, 0x0a, 189},
- {31, 0x0a, 189},
- {41, 0x0a, 189},
- {56, 0x0b, 189},
- },
- /* 141 */
- {
- {3, 0x0a, 190},
- {6, 0x0a, 190},
- {10, 0x0a, 190},
- {15, 0x0a, 190},
- {24, 0x0a, 190},
- {31, 0x0a, 190},
- {41, 0x0a, 190},
- {56, 0x0b, 190},
- {3, 0x0a, 196},
- {6, 0x0a, 196},
- {10, 0x0a, 196},
- {15, 0x0a, 196},
- {24, 0x0a, 196},
- {31, 0x0a, 196},
- {41, 0x0a, 196},
- {56, 0x0b, 196},
- },
- /* 142 */
- {
- {1, 0x0a, 198},
- {22, 0x0b, 198},
- {1, 0x0a, 228},
- {22, 0x0b, 228},
- {1, 0x0a, 232},
- {22, 0x0b, 232},
- {1, 0x0a, 233},
- {22, 0x0b, 233},
- {0, 0x1b, 1},
- {0, 0x0b, 135},
- {0, 0x0b, 137},
- {0, 0x0b, 138},
- {0, 0x0b, 139},
- {0, 0x0b, 140},
- {0, 0x0b, 141},
- {0, 0x0b, 143},
- },
- /* 143 */
- {
- {2, 0x0a, 198},
- {9, 0x0a, 198},
- {23, 0x0a, 198},
- {40, 0x0b, 198},
- {2, 0x0a, 228},
- {9, 0x0a, 228},
- {23, 0x0a, 228},
- {40, 0x0b, 228},
- {2, 0x0a, 232},
- {9, 0x0a, 232},
- {23, 0x0a, 232},
- {40, 0x0b, 232},
- {2, 0x0a, 233},
- {9, 0x0a, 233},
- {23, 0x0a, 233},
- {40, 0x0b, 233},
- },
- /* 144 */
- {
- {3, 0x0a, 198},
- {6, 0x0a, 198},
- {10, 0x0a, 198},
- {15, 0x0a, 198},
- {24, 0x0a, 198},
- {31, 0x0a, 198},
- {41, 0x0a, 198},
- {56, 0x0b, 198},
- {3, 0x0a, 228},
- {6, 0x0a, 228},
- {10, 0x0a, 228},
- {15, 0x0a, 228},
- {24, 0x0a, 228},
- {31, 0x0a, 228},
- {41, 0x0a, 228},
- {56, 0x0b, 228},
- },
- /* 145 */
- {
- {3, 0x0a, 232},
- {6, 0x0a, 232},
- {10, 0x0a, 232},
- {15, 0x0a, 232},
- {24, 0x0a, 232},
- {31, 0x0a, 232},
- {41, 0x0a, 232},
- {56, 0x0b, 232},
- {3, 0x0a, 233},
- {6, 0x0a, 233},
- {10, 0x0a, 233},
- {15, 0x0a, 233},
- {24, 0x0a, 233},
- {31, 0x0a, 233},
- {41, 0x0a, 233},
- {56, 0x0b, 233},
- },
- /* 146 */
- {
- {1, 0x1a, 1},
- {22, 0x1b, 1},
- {1, 0x0a, 135},
- {22, 0x0b, 135},
- {1, 0x0a, 137},
- {22, 0x0b, 137},
- {1, 0x0a, 138},
- {22, 0x0b, 138},
- {1, 0x0a, 139},
- {22, 0x0b, 139},
- {1, 0x0a, 140},
- {22, 0x0b, 140},
- {1, 0x0a, 141},
- {22, 0x0b, 141},
- {1, 0x0a, 143},
- {22, 0x0b, 143},
- },
- /* 147 */
- {
- {2, 0x1a, 1},
- {9, 0x1a, 1},
- {23, 0x1a, 1},
- {40, 0x1b, 1},
- {2, 0x0a, 135},
- {9, 0x0a, 135},
- {23, 0x0a, 135},
- {40, 0x0b, 135},
- {2, 0x0a, 137},
- {9, 0x0a, 137},
- {23, 0x0a, 137},
- {40, 0x0b, 137},
- {2, 0x0a, 138},
- {9, 0x0a, 138},
- {23, 0x0a, 138},
- {40, 0x0b, 138},
- },
- /* 148 */
- {
- {3, 0x1a, 1},
- {6, 0x1a, 1},
- {10, 0x1a, 1},
- {15, 0x1a, 1},
- {24, 0x1a, 1},
- {31, 0x1a, 1},
- {41, 0x1a, 1},
- {56, 0x1b, 1},
- {3, 0x0a, 135},
- {6, 0x0a, 135},
- {10, 0x0a, 135},
- {15, 0x0a, 135},
- {24, 0x0a, 135},
- {31, 0x0a, 135},
- {41, 0x0a, 135},
- {56, 0x0b, 135},
- },
- /* 149 */
- {
- {3, 0x0a, 137},
- {6, 0x0a, 137},
- {10, 0x0a, 137},
- {15, 0x0a, 137},
- {24, 0x0a, 137},
- {31, 0x0a, 137},
- {41, 0x0a, 137},
- {56, 0x0b, 137},
- {3, 0x0a, 138},
- {6, 0x0a, 138},
- {10, 0x0a, 138},
- {15, 0x0a, 138},
- {24, 0x0a, 138},
- {31, 0x0a, 138},
- {41, 0x0a, 138},
- {56, 0x0b, 138},
- },
- /* 150 */
- {
- {2, 0x0a, 139},
- {9, 0x0a, 139},
- {23, 0x0a, 139},
- {40, 0x0b, 139},
- {2, 0x0a, 140},
- {9, 0x0a, 140},
- {23, 0x0a, 140},
- {40, 0x0b, 140},
- {2, 0x0a, 141},
- {9, 0x0a, 141},
- {23, 0x0a, 141},
- {40, 0x0b, 141},
- {2, 0x0a, 143},
- {9, 0x0a, 143},
- {23, 0x0a, 143},
- {40, 0x0b, 143},
- },
- /* 151 */
- {
- {3, 0x0a, 139},
- {6, 0x0a, 139},
- {10, 0x0a, 139},
- {15, 0x0a, 139},
- {24, 0x0a, 139},
- {31, 0x0a, 139},
- {41, 0x0a, 139},
- {56, 0x0b, 139},
- {3, 0x0a, 140},
- {6, 0x0a, 140},
- {10, 0x0a, 140},
- {15, 0x0a, 140},
- {24, 0x0a, 140},
- {31, 0x0a, 140},
- {41, 0x0a, 140},
- {56, 0x0b, 140},
- },
- /* 152 */
- {
- {3, 0x0a, 141},
- {6, 0x0a, 141},
- {10, 0x0a, 141},
- {15, 0x0a, 141},
- {24, 0x0a, 141},
- {31, 0x0a, 141},
- {41, 0x0a, 141},
- {56, 0x0b, 141},
- {3, 0x0a, 143},
- {6, 0x0a, 143},
- {10, 0x0a, 143},
- {15, 0x0a, 143},
- {24, 0x0a, 143},
- {31, 0x0a, 143},
- {41, 0x0a, 143},
- {56, 0x0b, 143},
- },
- /* 153 */
- {
- {157, 0x00, 0},
- {158, 0x00, 0},
- {160, 0x00, 0},
- {161, 0x00, 0},
- {164, 0x00, 0},
- {165, 0x00, 0},
- {167, 0x00, 0},
- {168, 0x00, 0},
- {172, 0x00, 0},
- {173, 0x00, 0},
- {175, 0x00, 0},
- {177, 0x00, 0},
- {182, 0x00, 0},
- {185, 0x00, 0},
- {191, 0x00, 0},
- {207, 0x00, 0},
- },
- /* 154 */
- {
- {0, 0x0b, 147},
- {0, 0x0b, 149},
- {0, 0x0b, 150},
- {0, 0x0b, 151},
- {0, 0x0b, 152},
- {0, 0x0b, 155},
- {0, 0x0b, 157},
- {0, 0x0b, 158},
- {0, 0x0b, 165},
- {0, 0x0b, 166},
- {0, 0x0b, 168},
- {0, 0x0b, 174},
- {0, 0x0b, 175},
- {0, 0x0b, 180},
- {0, 0x0b, 182},
- {0, 0x0b, 183},
- },
- /* 155 */
- {
- {1, 0x0a, 147},
- {22, 0x0b, 147},
- {1, 0x0a, 149},
- {22, 0x0b, 149},
- {1, 0x0a, 150},
- {22, 0x0b, 150},
- {1, 0x0a, 151},
- {22, 0x0b, 151},
- {1, 0x0a, 152},
- {22, 0x0b, 152},
- {1, 0x0a, 155},
- {22, 0x0b, 155},
- {1, 0x0a, 157},
- {22, 0x0b, 157},
- {1, 0x0a, 158},
- {22, 0x0b, 158},
- },
- /* 156 */
- {
- {2, 0x0a, 147},
- {9, 0x0a, 147},
- {23, 0x0a, 147},
- {40, 0x0b, 147},
- {2, 0x0a, 149},
- {9, 0x0a, 149},
- {23, 0x0a, 149},
- {40, 0x0b, 149},
- {2, 0x0a, 150},
- {9, 0x0a, 150},
- {23, 0x0a, 150},
- {40, 0x0b, 150},
- {2, 0x0a, 151},
- {9, 0x0a, 151},
- {23, 0x0a, 151},
- {40, 0x0b, 151},
- },
- /* 157 */
- {
- {3, 0x0a, 147},
- {6, 0x0a, 147},
- {10, 0x0a, 147},
- {15, 0x0a, 147},
- {24, 0x0a, 147},
- {31, 0x0a, 147},
- {41, 0x0a, 147},
- {56, 0x0b, 147},
- {3, 0x0a, 149},
- {6, 0x0a, 149},
- {10, 0x0a, 149},
- {15, 0x0a, 149},
- {24, 0x0a, 149},
- {31, 0x0a, 149},
- {41, 0x0a, 149},
- {56, 0x0b, 149},
- },
- /* 158 */
- {
- {3, 0x0a, 150},
- {6, 0x0a, 150},
- {10, 0x0a, 150},
- {15, 0x0a, 150},
- {24, 0x0a, 150},
- {31, 0x0a, 150},
- {41, 0x0a, 150},
- {56, 0x0b, 150},
- {3, 0x0a, 151},
- {6, 0x0a, 151},
- {10, 0x0a, 151},
- {15, 0x0a, 151},
- {24, 0x0a, 151},
- {31, 0x0a, 151},
- {41, 0x0a, 151},
- {56, 0x0b, 151},
- },
- /* 159 */
- {
- {2, 0x0a, 152},
- {9, 0x0a, 152},
- {23, 0x0a, 152},
- {40, 0x0b, 152},
- {2, 0x0a, 155},
- {9, 0x0a, 155},
- {23, 0x0a, 155},
- {40, 0x0b, 155},
- {2, 0x0a, 157},
- {9, 0x0a, 157},
- {23, 0x0a, 157},
- {40, 0x0b, 157},
- {2, 0x0a, 158},
- {9, 0x0a, 158},
- {23, 0x0a, 158},
- {40, 0x0b, 158},
- },
- /* 160 */
- {
- {3, 0x0a, 152},
- {6, 0x0a, 152},
- {10, 0x0a, 152},
- {15, 0x0a, 152},
- {24, 0x0a, 152},
- {31, 0x0a, 152},
- {41, 0x0a, 152},
- {56, 0x0b, 152},
- {3, 0x0a, 155},
- {6, 0x0a, 155},
- {10, 0x0a, 155},
- {15, 0x0a, 155},
- {24, 0x0a, 155},
- {31, 0x0a, 155},
- {41, 0x0a, 155},
- {56, 0x0b, 155},
- },
- /* 161 */
- {
- {3, 0x0a, 157},
- {6, 0x0a, 157},
- {10, 0x0a, 157},
- {15, 0x0a, 157},
- {24, 0x0a, 157},
- {31, 0x0a, 157},
- {41, 0x0a, 157},
- {56, 0x0b, 157},
- {3, 0x0a, 158},
- {6, 0x0a, 158},
- {10, 0x0a, 158},
- {15, 0x0a, 158},
- {24, 0x0a, 158},
- {31, 0x0a, 158},
- {41, 0x0a, 158},
- {56, 0x0b, 158},
- },
- /* 162 */
- {
- {1, 0x0a, 165},
- {22, 0x0b, 165},
- {1, 0x0a, 166},
- {22, 0x0b, 166},
- {1, 0x0a, 168},
- {22, 0x0b, 168},
- {1, 0x0a, 174},
- {22, 0x0b, 174},
- {1, 0x0a, 175},
- {22, 0x0b, 175},
- {1, 0x0a, 180},
- {22, 0x0b, 180},
- {1, 0x0a, 182},
- {22, 0x0b, 182},
- {1, 0x0a, 183},
- {22, 0x0b, 183},
- },
- /* 163 */
- {
- {2, 0x0a, 165},
- {9, 0x0a, 165},
- {23, 0x0a, 165},
- {40, 0x0b, 165},
- {2, 0x0a, 166},
- {9, 0x0a, 166},
- {23, 0x0a, 166},
- {40, 0x0b, 166},
- {2, 0x0a, 168},
- {9, 0x0a, 168},
- {23, 0x0a, 168},
- {40, 0x0b, 168},
- {2, 0x0a, 174},
- {9, 0x0a, 174},
- {23, 0x0a, 174},
- {40, 0x0b, 174},
- },
- /* 164 */
- {
- {3, 0x0a, 165},
- {6, 0x0a, 165},
- {10, 0x0a, 165},
- {15, 0x0a, 165},
- {24, 0x0a, 165},
- {31, 0x0a, 165},
- {41, 0x0a, 165},
- {56, 0x0b, 165},
- {3, 0x0a, 166},
- {6, 0x0a, 166},
- {10, 0x0a, 166},
- {15, 0x0a, 166},
- {24, 0x0a, 166},
- {31, 0x0a, 166},
- {41, 0x0a, 166},
- {56, 0x0b, 166},
- },
- /* 165 */
- {
- {3, 0x0a, 168},
- {6, 0x0a, 168},
- {10, 0x0a, 168},
- {15, 0x0a, 168},
- {24, 0x0a, 168},
- {31, 0x0a, 168},
- {41, 0x0a, 168},
- {56, 0x0b, 168},
- {3, 0x0a, 174},
- {6, 0x0a, 174},
- {10, 0x0a, 174},
- {15, 0x0a, 174},
- {24, 0x0a, 174},
- {31, 0x0a, 174},
- {41, 0x0a, 174},
- {56, 0x0b, 174},
- },
- /* 166 */
- {
- {2, 0x0a, 175},
- {9, 0x0a, 175},
- {23, 0x0a, 175},
- {40, 0x0b, 175},
- {2, 0x0a, 180},
- {9, 0x0a, 180},
- {23, 0x0a, 180},
- {40, 0x0b, 180},
- {2, 0x0a, 182},
- {9, 0x0a, 182},
- {23, 0x0a, 182},
- {40, 0x0b, 182},
- {2, 0x0a, 183},
- {9, 0x0a, 183},
- {23, 0x0a, 183},
- {40, 0x0b, 183},
- },
- /* 167 */
- {
- {3, 0x0a, 175},
- {6, 0x0a, 175},
- {10, 0x0a, 175},
- {15, 0x0a, 175},
- {24, 0x0a, 175},
- {31, 0x0a, 175},
- {41, 0x0a, 175},
- {56, 0x0b, 175},
- {3, 0x0a, 180},
- {6, 0x0a, 180},
- {10, 0x0a, 180},
- {15, 0x0a, 180},
- {24, 0x0a, 180},
- {31, 0x0a, 180},
- {41, 0x0a, 180},
- {56, 0x0b, 180},
- },
- /* 168 */
- {
- {3, 0x0a, 182},
- {6, 0x0a, 182},
- {10, 0x0a, 182},
- {15, 0x0a, 182},
- {24, 0x0a, 182},
- {31, 0x0a, 182},
- {41, 0x0a, 182},
- {56, 0x0b, 182},
- {3, 0x0a, 183},
- {6, 0x0a, 183},
- {10, 0x0a, 183},
- {15, 0x0a, 183},
- {24, 0x0a, 183},
- {31, 0x0a, 183},
- {41, 0x0a, 183},
- {56, 0x0b, 183},
- },
- /* 169 */
- {
- {0, 0x0b, 188},
- {0, 0x0b, 191},
- {0, 0x0b, 197},
- {0, 0x0b, 231},
- {0, 0x0b, 239},
- {176, 0x00, 0},
- {178, 0x00, 0},
- {179, 0x00, 0},
- {183, 0x00, 0},
- {184, 0x00, 0},
- {186, 0x00, 0},
- {187, 0x00, 0},
- {192, 0x00, 0},
- {199, 0x00, 0},
- {208, 0x00, 0},
- {223, 0x00, 0},
- },
- /* 170 */
- {
- {1, 0x0a, 188},
- {22, 0x0b, 188},
- {1, 0x0a, 191},
- {22, 0x0b, 191},
- {1, 0x0a, 197},
- {22, 0x0b, 197},
- {1, 0x0a, 231},
- {22, 0x0b, 231},
- {1, 0x0a, 239},
- {22, 0x0b, 239},
- {0, 0x0b, 9},
- {0, 0x0b, 142},
- {0, 0x0b, 144},
- {0, 0x0b, 145},
- {0, 0x0b, 148},
- {0, 0x0b, 159},
- },
- /* 171 */
- {
- {2, 0x0a, 188},
- {9, 0x0a, 188},
- {23, 0x0a, 188},
- {40, 0x0b, 188},
- {2, 0x0a, 191},
- {9, 0x0a, 191},
- {23, 0x0a, 191},
- {40, 0x0b, 191},
- {2, 0x0a, 197},
- {9, 0x0a, 197},
- {23, 0x0a, 197},
- {40, 0x0b, 197},
- {2, 0x0a, 231},
- {9, 0x0a, 231},
- {23, 0x0a, 231},
- {40, 0x0b, 231},
- },
- /* 172 */
- {
- {3, 0x0a, 188},
- {6, 0x0a, 188},
- {10, 0x0a, 188},
- {15, 0x0a, 188},
- {24, 0x0a, 188},
- {31, 0x0a, 188},
- {41, 0x0a, 188},
- {56, 0x0b, 188},
- {3, 0x0a, 191},
- {6, 0x0a, 191},
- {10, 0x0a, 191},
- {15, 0x0a, 191},
- {24, 0x0a, 191},
- {31, 0x0a, 191},
- {41, 0x0a, 191},
- {56, 0x0b, 191},
- },
- /* 173 */
- {
- {3, 0x0a, 197},
- {6, 0x0a, 197},
- {10, 0x0a, 197},
- {15, 0x0a, 197},
- {24, 0x0a, 197},
- {31, 0x0a, 197},
- {41, 0x0a, 197},
- {56, 0x0b, 197},
- {3, 0x0a, 231},
- {6, 0x0a, 231},
- {10, 0x0a, 231},
- {15, 0x0a, 231},
- {24, 0x0a, 231},
- {31, 0x0a, 231},
- {41, 0x0a, 231},
- {56, 0x0b, 231},
- },
- /* 174 */
- {
- {2, 0x0a, 239},
- {9, 0x0a, 239},
- {23, 0x0a, 239},
- {40, 0x0b, 239},
- {1, 0x0a, 9},
- {22, 0x0b, 9},
- {1, 0x0a, 142},
- {22, 0x0b, 142},
- {1, 0x0a, 144},
- {22, 0x0b, 144},
- {1, 0x0a, 145},
- {22, 0x0b, 145},
- {1, 0x0a, 148},
- {22, 0x0b, 148},
- {1, 0x0a, 159},
- {22, 0x0b, 159},
- },
- /* 175 */
- {
- {3, 0x0a, 239},
- {6, 0x0a, 239},
- {10, 0x0a, 239},
- {15, 0x0a, 239},
- {24, 0x0a, 239},
- {31, 0x0a, 239},
- {41, 0x0a, 239},
- {56, 0x0b, 239},
- {2, 0x0a, 9},
- {9, 0x0a, 9},
- {23, 0x0a, 9},
- {40, 0x0b, 9},
- {2, 0x0a, 142},
- {9, 0x0a, 142},
- {23, 0x0a, 142},
- {40, 0x0b, 142},
- },
- /* 176 */
- {
- {3, 0x0a, 9},
- {6, 0x0a, 9},
- {10, 0x0a, 9},
- {15, 0x0a, 9},
- {24, 0x0a, 9},
- {31, 0x0a, 9},
- {41, 0x0a, 9},
- {56, 0x0b, 9},
- {3, 0x0a, 142},
- {6, 0x0a, 142},
- {10, 0x0a, 142},
- {15, 0x0a, 142},
- {24, 0x0a, 142},
- {31, 0x0a, 142},
- {41, 0x0a, 142},
- {56, 0x0b, 142},
- },
- /* 177 */
- {
- {2, 0x0a, 144},
- {9, 0x0a, 144},
- {23, 0x0a, 144},
- {40, 0x0b, 144},
- {2, 0x0a, 145},
- {9, 0x0a, 145},
- {23, 0x0a, 145},
- {40, 0x0b, 145},
- {2, 0x0a, 148},
- {9, 0x0a, 148},
- {23, 0x0a, 148},
- {40, 0x0b, 148},
- {2, 0x0a, 159},
- {9, 0x0a, 159},
- {23, 0x0a, 159},
- {40, 0x0b, 159},
- },
- /* 178 */
- {
- {3, 0x0a, 144},
- {6, 0x0a, 144},
- {10, 0x0a, 144},
- {15, 0x0a, 144},
- {24, 0x0a, 144},
- {31, 0x0a, 144},
- {41, 0x0a, 144},
- {56, 0x0b, 144},
- {3, 0x0a, 145},
- {6, 0x0a, 145},
- {10, 0x0a, 145},
- {15, 0x0a, 145},
- {24, 0x0a, 145},
- {31, 0x0a, 145},
- {41, 0x0a, 145},
- {56, 0x0b, 145},
- },
- /* 179 */
- {
- {3, 0x0a, 148},
- {6, 0x0a, 148},
- {10, 0x0a, 148},
- {15, 0x0a, 148},
- {24, 0x0a, 148},
- {31, 0x0a, 148},
- {41, 0x0a, 148},
- {56, 0x0b, 148},
- {3, 0x0a, 159},
- {6, 0x0a, 159},
- {10, 0x0a, 159},
- {15, 0x0a, 159},
- {24, 0x0a, 159},
- {31, 0x0a, 159},
- {41, 0x0a, 159},
- {56, 0x0b, 159},
- },
- /* 180 */
- {
- {0, 0x0b, 171},
- {0, 0x0b, 206},
- {0, 0x0b, 215},
- {0, 0x0b, 225},
- {0, 0x0b, 236},
- {0, 0x0b, 237},
- {188, 0x00, 0},
- {189, 0x00, 0},
- {193, 0x00, 0},
- {196, 0x00, 0},
- {200, 0x00, 0},
- {203, 0x00, 0},
- {209, 0x00, 0},
- {216, 0x00, 0},
- {224, 0x00, 0},
- {238, 0x00, 0},
- },
- /* 181 */
- {
- {1, 0x0a, 171},
- {22, 0x0b, 171},
- {1, 0x0a, 206},
- {22, 0x0b, 206},
- {1, 0x0a, 215},
- {22, 0x0b, 215},
- {1, 0x0a, 225},
- {22, 0x0b, 225},
- {1, 0x0a, 236},
- {22, 0x0b, 236},
- {1, 0x0a, 237},
- {22, 0x0b, 237},
- {0, 0x0b, 199},
- {0, 0x0b, 207},
- {0, 0x0b, 234},
- {0, 0x0b, 235},
- },
- /* 182 */
- {
- {2, 0x0a, 171},
- {9, 0x0a, 171},
- {23, 0x0a, 171},
- {40, 0x0b, 171},
- {2, 0x0a, 206},
- {9, 0x0a, 206},
- {23, 0x0a, 206},
- {40, 0x0b, 206},
- {2, 0x0a, 215},
- {9, 0x0a, 215},
- {23, 0x0a, 215},
- {40, 0x0b, 215},
- {2, 0x0a, 225},
- {9, 0x0a, 225},
- {23, 0x0a, 225},
- {40, 0x0b, 225},
- },
- /* 183 */
- {
- {3, 0x0a, 171},
- {6, 0x0a, 171},
- {10, 0x0a, 171},
- {15, 0x0a, 171},
- {24, 0x0a, 171},
- {31, 0x0a, 171},
- {41, 0x0a, 171},
- {56, 0x0b, 171},
- {3, 0x0a, 206},
- {6, 0x0a, 206},
- {10, 0x0a, 206},
- {15, 0x0a, 206},
- {24, 0x0a, 206},
- {31, 0x0a, 206},
- {41, 0x0a, 206},
- {56, 0x0b, 206},
- },
- /* 184 */
- {
- {3, 0x0a, 215},
- {6, 0x0a, 215},
- {10, 0x0a, 215},
- {15, 0x0a, 215},
- {24, 0x0a, 215},
- {31, 0x0a, 215},
- {41, 0x0a, 215},
- {56, 0x0b, 215},
- {3, 0x0a, 225},
- {6, 0x0a, 225},
- {10, 0x0a, 225},
- {15, 0x0a, 225},
- {24, 0x0a, 225},
- {31, 0x0a, 225},
- {41, 0x0a, 225},
- {56, 0x0b, 225},
- },
- /* 185 */
- {
- {2, 0x0a, 236},
- {9, 0x0a, 236},
- {23, 0x0a, 236},
- {40, 0x0b, 236},
- {2, 0x0a, 237},
- {9, 0x0a, 237},
- {23, 0x0a, 237},
- {40, 0x0b, 237},
- {1, 0x0a, 199},
- {22, 0x0b, 199},
- {1, 0x0a, 207},
- {22, 0x0b, 207},
- {1, 0x0a, 234},
- {22, 0x0b, 234},
- {1, 0x0a, 235},
- {22, 0x0b, 235},
- },
- /* 186 */
- {
- {3, 0x0a, 236},
- {6, 0x0a, 236},
- {10, 0x0a, 236},
- {15, 0x0a, 236},
- {24, 0x0a, 236},
- {31, 0x0a, 236},
- {41, 0x0a, 236},
- {56, 0x0b, 236},
- {3, 0x0a, 237},
- {6, 0x0a, 237},
- {10, 0x0a, 237},
- {15, 0x0a, 237},
- {24, 0x0a, 237},
- {31, 0x0a, 237},
- {41, 0x0a, 237},
- {56, 0x0b, 237},
- },
- /* 187 */
- {
- {2, 0x0a, 199},
- {9, 0x0a, 199},
- {23, 0x0a, 199},
- {40, 0x0b, 199},
- {2, 0x0a, 207},
- {9, 0x0a, 207},
- {23, 0x0a, 207},
- {40, 0x0b, 207},
- {2, 0x0a, 234},
- {9, 0x0a, 234},
- {23, 0x0a, 234},
- {40, 0x0b, 234},
- {2, 0x0a, 235},
- {9, 0x0a, 235},
- {23, 0x0a, 235},
- {40, 0x0b, 235},
- },
- /* 188 */
- {
- {3, 0x0a, 199},
- {6, 0x0a, 199},
- {10, 0x0a, 199},
- {15, 0x0a, 199},
- {24, 0x0a, 199},
- {31, 0x0a, 199},
- {41, 0x0a, 199},
- {56, 0x0b, 199},
- {3, 0x0a, 207},
- {6, 0x0a, 207},
- {10, 0x0a, 207},
- {15, 0x0a, 207},
- {24, 0x0a, 207},
- {31, 0x0a, 207},
- {41, 0x0a, 207},
- {56, 0x0b, 207},
- },
- /* 189 */
- {
- {3, 0x0a, 234},
- {6, 0x0a, 234},
- {10, 0x0a, 234},
- {15, 0x0a, 234},
- {24, 0x0a, 234},
- {31, 0x0a, 234},
- {41, 0x0a, 234},
- {56, 0x0b, 234},
- {3, 0x0a, 235},
- {6, 0x0a, 235},
- {10, 0x0a, 235},
- {15, 0x0a, 235},
- {24, 0x0a, 235},
- {31, 0x0a, 235},
- {41, 0x0a, 235},
- {56, 0x0b, 235},
- },
- /* 190 */
- {
- {194, 0x00, 0},
- {195, 0x00, 0},
- {197, 0x00, 0},
- {198, 0x00, 0},
- {201, 0x00, 0},
- {202, 0x00, 0},
- {204, 0x00, 0},
- {205, 0x00, 0},
- {210, 0x00, 0},
- {213, 0x00, 0},
- {217, 0x00, 0},
- {220, 0x00, 0},
- {225, 0x00, 0},
- {231, 0x00, 0},
- {239, 0x00, 0},
- {246, 0x00, 0},
- },
- /* 191 */
- {
- {0, 0x0b, 192},
- {0, 0x0b, 193},
- {0, 0x0b, 200},
- {0, 0x0b, 201},
- {0, 0x0b, 202},
- {0, 0x0b, 205},
- {0, 0x0b, 210},
- {0, 0x0b, 213},
- {0, 0x0b, 218},
- {0, 0x0b, 219},
- {0, 0x0b, 238},
- {0, 0x0b, 240},
- {0, 0x0b, 242},
- {0, 0x0b, 243},
- {0, 0x0b, 255},
- {206, 0x00, 0},
- },
- /* 192 */
- {
- {1, 0x0a, 192},
- {22, 0x0b, 192},
- {1, 0x0a, 193},
- {22, 0x0b, 193},
- {1, 0x0a, 200},
- {22, 0x0b, 200},
- {1, 0x0a, 201},
- {22, 0x0b, 201},
- {1, 0x0a, 202},
- {22, 0x0b, 202},
- {1, 0x0a, 205},
- {22, 0x0b, 205},
- {1, 0x0a, 210},
- {22, 0x0b, 210},
- {1, 0x0a, 213},
- {22, 0x0b, 213},
- },
- /* 193 */
- {
- {2, 0x0a, 192},
- {9, 0x0a, 192},
- {23, 0x0a, 192},
- {40, 0x0b, 192},
- {2, 0x0a, 193},
- {9, 0x0a, 193},
- {23, 0x0a, 193},
- {40, 0x0b, 193},
- {2, 0x0a, 200},
- {9, 0x0a, 200},
- {23, 0x0a, 200},
- {40, 0x0b, 200},
- {2, 0x0a, 201},
- {9, 0x0a, 201},
- {23, 0x0a, 201},
- {40, 0x0b, 201},
- },
- /* 194 */
- {
- {3, 0x0a, 192},
- {6, 0x0a, 192},
- {10, 0x0a, 192},
- {15, 0x0a, 192},
- {24, 0x0a, 192},
- {31, 0x0a, 192},
- {41, 0x0a, 192},
- {56, 0x0b, 192},
- {3, 0x0a, 193},
- {6, 0x0a, 193},
- {10, 0x0a, 193},
- {15, 0x0a, 193},
- {24, 0x0a, 193},
- {31, 0x0a, 193},
- {41, 0x0a, 193},
- {56, 0x0b, 193},
- },
- /* 195 */
- {
- {3, 0x0a, 200},
- {6, 0x0a, 200},
- {10, 0x0a, 200},
- {15, 0x0a, 200},
- {24, 0x0a, 200},
- {31, 0x0a, 200},
- {41, 0x0a, 200},
- {56, 0x0b, 200},
- {3, 0x0a, 201},
- {6, 0x0a, 201},
- {10, 0x0a, 201},
- {15, 0x0a, 201},
- {24, 0x0a, 201},
- {31, 0x0a, 201},
- {41, 0x0a, 201},
- {56, 0x0b, 201},
- },
- /* 196 */
- {
- {2, 0x0a, 202},
- {9, 0x0a, 202},
- {23, 0x0a, 202},
- {40, 0x0b, 202},
- {2, 0x0a, 205},
- {9, 0x0a, 205},
- {23, 0x0a, 205},
- {40, 0x0b, 205},
- {2, 0x0a, 210},
- {9, 0x0a, 210},
- {23, 0x0a, 210},
- {40, 0x0b, 210},
- {2, 0x0a, 213},
- {9, 0x0a, 213},
- {23, 0x0a, 213},
- {40, 0x0b, 213},
- },
- /* 197 */
- {
- {3, 0x0a, 202},
- {6, 0x0a, 202},
- {10, 0x0a, 202},
- {15, 0x0a, 202},
- {24, 0x0a, 202},
- {31, 0x0a, 202},
- {41, 0x0a, 202},
- {56, 0x0b, 202},
- {3, 0x0a, 205},
- {6, 0x0a, 205},
- {10, 0x0a, 205},
- {15, 0x0a, 205},
- {24, 0x0a, 205},
- {31, 0x0a, 205},
- {41, 0x0a, 205},
- {56, 0x0b, 205},
- },
- /* 198 */
- {
- {3, 0x0a, 210},
- {6, 0x0a, 210},
- {10, 0x0a, 210},
- {15, 0x0a, 210},
- {24, 0x0a, 210},
- {31, 0x0a, 210},
- {41, 0x0a, 210},
- {56, 0x0b, 210},
- {3, 0x0a, 213},
- {6, 0x0a, 213},
- {10, 0x0a, 213},
- {15, 0x0a, 213},
- {24, 0x0a, 213},
- {31, 0x0a, 213},
- {41, 0x0a, 213},
- {56, 0x0b, 213},
- },
- /* 199 */
- {
- {1, 0x0a, 218},
- {22, 0x0b, 218},
- {1, 0x0a, 219},
- {22, 0x0b, 219},
- {1, 0x0a, 238},
- {22, 0x0b, 238},
- {1, 0x0a, 240},
- {22, 0x0b, 240},
- {1, 0x0a, 242},
- {22, 0x0b, 242},
- {1, 0x0a, 243},
- {22, 0x0b, 243},
- {1, 0x0a, 255},
- {22, 0x0b, 255},
- {0, 0x0b, 203},
- {0, 0x0b, 204},
- },
- /* 200 */
- {
- {2, 0x0a, 218},
- {9, 0x0a, 218},
- {23, 0x0a, 218},
- {40, 0x0b, 218},
- {2, 0x0a, 219},
- {9, 0x0a, 219},
- {23, 0x0a, 219},
- {40, 0x0b, 219},
- {2, 0x0a, 238},
- {9, 0x0a, 238},
- {23, 0x0a, 238},
- {40, 0x0b, 238},
- {2, 0x0a, 240},
- {9, 0x0a, 240},
- {23, 0x0a, 240},
- {40, 0x0b, 240},
- },
- /* 201 */
- {
- {3, 0x0a, 218},
- {6, 0x0a, 218},
- {10, 0x0a, 218},
- {15, 0x0a, 218},
- {24, 0x0a, 218},
- {31, 0x0a, 218},
- {41, 0x0a, 218},
- {56, 0x0b, 218},
- {3, 0x0a, 219},
- {6, 0x0a, 219},
- {10, 0x0a, 219},
- {15, 0x0a, 219},
- {24, 0x0a, 219},
- {31, 0x0a, 219},
- {41, 0x0a, 219},
- {56, 0x0b, 219},
- },
- /* 202 */
- {
- {3, 0x0a, 238},
- {6, 0x0a, 238},
- {10, 0x0a, 238},
- {15, 0x0a, 238},
- {24, 0x0a, 238},
- {31, 0x0a, 238},
- {41, 0x0a, 238},
- {56, 0x0b, 238},
- {3, 0x0a, 240},
- {6, 0x0a, 240},
- {10, 0x0a, 240},
- {15, 0x0a, 240},
- {24, 0x0a, 240},
- {31, 0x0a, 240},
- {41, 0x0a, 240},
- {56, 0x0b, 240},
- },
- /* 203 */
- {
- {2, 0x0a, 242},
- {9, 0x0a, 242},
- {23, 0x0a, 242},
- {40, 0x0b, 242},
- {2, 0x0a, 243},
- {9, 0x0a, 243},
- {23, 0x0a, 243},
- {40, 0x0b, 243},
- {2, 0x0a, 255},
- {9, 0x0a, 255},
- {23, 0x0a, 255},
- {40, 0x0b, 255},
- {1, 0x0a, 203},
- {22, 0x0b, 203},
- {1, 0x0a, 204},
- {22, 0x0b, 204},
- },
- /* 204 */
- {
- {3, 0x0a, 242},
- {6, 0x0a, 242},
- {10, 0x0a, 242},
- {15, 0x0a, 242},
- {24, 0x0a, 242},
- {31, 0x0a, 242},
- {41, 0x0a, 242},
- {56, 0x0b, 242},
- {3, 0x0a, 243},
- {6, 0x0a, 243},
- {10, 0x0a, 243},
- {15, 0x0a, 243},
- {24, 0x0a, 243},
- {31, 0x0a, 243},
- {41, 0x0a, 243},
- {56, 0x0b, 243},
- },
- /* 205 */
- {
- {3, 0x0a, 255},
- {6, 0x0a, 255},
- {10, 0x0a, 255},
- {15, 0x0a, 255},
- {24, 0x0a, 255},
- {31, 0x0a, 255},
- {41, 0x0a, 255},
- {56, 0x0b, 255},
- {2, 0x0a, 203},
- {9, 0x0a, 203},
- {23, 0x0a, 203},
- {40, 0x0b, 203},
- {2, 0x0a, 204},
- {9, 0x0a, 204},
- {23, 0x0a, 204},
- {40, 0x0b, 204},
- },
- /* 206 */
- {
- {3, 0x0a, 203},
- {6, 0x0a, 203},
- {10, 0x0a, 203},
- {15, 0x0a, 203},
- {24, 0x0a, 203},
- {31, 0x0a, 203},
- {41, 0x0a, 203},
- {56, 0x0b, 203},
- {3, 0x0a, 204},
- {6, 0x0a, 204},
- {10, 0x0a, 204},
- {15, 0x0a, 204},
- {24, 0x0a, 204},
- {31, 0x0a, 204},
- {41, 0x0a, 204},
- {56, 0x0b, 204},
- },
- /* 207 */
- {
- {211, 0x00, 0},
- {212, 0x00, 0},
- {214, 0x00, 0},
- {215, 0x00, 0},
- {218, 0x00, 0},
- {219, 0x00, 0},
- {221, 0x00, 0},
- {222, 0x00, 0},
- {226, 0x00, 0},
- {228, 0x00, 0},
- {232, 0x00, 0},
- {235, 0x00, 0},
- {240, 0x00, 0},
- {243, 0x00, 0},
- {247, 0x00, 0},
- {250, 0x00, 0},
- },
- /* 208 */
- {
- {0, 0x0b, 211},
- {0, 0x0b, 212},
- {0, 0x0b, 214},
- {0, 0x0b, 221},
- {0, 0x0b, 222},
- {0, 0x0b, 223},
- {0, 0x0b, 241},
- {0, 0x0b, 244},
- {0, 0x0b, 245},
- {0, 0x0b, 246},
- {0, 0x0b, 247},
- {0, 0x0b, 248},
- {0, 0x0b, 250},
- {0, 0x0b, 251},
- {0, 0x0b, 252},
- {0, 0x0b, 253},
- },
- /* 209 */
- {
- {1, 0x0a, 211},
- {22, 0x0b, 211},
- {1, 0x0a, 212},
- {22, 0x0b, 212},
- {1, 0x0a, 214},
- {22, 0x0b, 214},
- {1, 0x0a, 221},
- {22, 0x0b, 221},
- {1, 0x0a, 222},
- {22, 0x0b, 222},
- {1, 0x0a, 223},
- {22, 0x0b, 223},
- {1, 0x0a, 241},
- {22, 0x0b, 241},
- {1, 0x0a, 244},
- {22, 0x0b, 244},
- },
- /* 210 */
- {
- {2, 0x0a, 211},
- {9, 0x0a, 211},
- {23, 0x0a, 211},
- {40, 0x0b, 211},
- {2, 0x0a, 212},
- {9, 0x0a, 212},
- {23, 0x0a, 212},
- {40, 0x0b, 212},
- {2, 0x0a, 214},
- {9, 0x0a, 214},
- {23, 0x0a, 214},
- {40, 0x0b, 214},
- {2, 0x0a, 221},
- {9, 0x0a, 221},
- {23, 0x0a, 221},
- {40, 0x0b, 221},
- },
- /* 211 */
- {
- {3, 0x0a, 211},
- {6, 0x0a, 211},
- {10, 0x0a, 211},
- {15, 0x0a, 211},
- {24, 0x0a, 211},
- {31, 0x0a, 211},
- {41, 0x0a, 211},
- {56, 0x0b, 211},
- {3, 0x0a, 212},
- {6, 0x0a, 212},
- {10, 0x0a, 212},
- {15, 0x0a, 212},
- {24, 0x0a, 212},
- {31, 0x0a, 212},
- {41, 0x0a, 212},
- {56, 0x0b, 212},
- },
- /* 212 */
- {
- {3, 0x0a, 214},
- {6, 0x0a, 214},
- {10, 0x0a, 214},
- {15, 0x0a, 214},
- {24, 0x0a, 214},
- {31, 0x0a, 214},
- {41, 0x0a, 214},
- {56, 0x0b, 214},
- {3, 0x0a, 221},
- {6, 0x0a, 221},
- {10, 0x0a, 221},
- {15, 0x0a, 221},
- {24, 0x0a, 221},
- {31, 0x0a, 221},
- {41, 0x0a, 221},
- {56, 0x0b, 221},
- },
- /* 213 */
- {
- {2, 0x0a, 222},
- {9, 0x0a, 222},
- {23, 0x0a, 222},
- {40, 0x0b, 222},
- {2, 0x0a, 223},
- {9, 0x0a, 223},
- {23, 0x0a, 223},
- {40, 0x0b, 223},
- {2, 0x0a, 241},
- {9, 0x0a, 241},
- {23, 0x0a, 241},
- {40, 0x0b, 241},
- {2, 0x0a, 244},
- {9, 0x0a, 244},
- {23, 0x0a, 244},
- {40, 0x0b, 244},
- },
- /* 214 */
- {
- {3, 0x0a, 222},
- {6, 0x0a, 222},
- {10, 0x0a, 222},
- {15, 0x0a, 222},
- {24, 0x0a, 222},
- {31, 0x0a, 222},
- {41, 0x0a, 222},
- {56, 0x0b, 222},
- {3, 0x0a, 223},
- {6, 0x0a, 223},
- {10, 0x0a, 223},
- {15, 0x0a, 223},
- {24, 0x0a, 223},
- {31, 0x0a, 223},
- {41, 0x0a, 223},
- {56, 0x0b, 223},
- },
- /* 215 */
- {
- {3, 0x0a, 241},
- {6, 0x0a, 241},
- {10, 0x0a, 241},
- {15, 0x0a, 241},
- {24, 0x0a, 241},
- {31, 0x0a, 241},
- {41, 0x0a, 241},
- {56, 0x0b, 241},
- {3, 0x0a, 244},
- {6, 0x0a, 244},
- {10, 0x0a, 244},
- {15, 0x0a, 244},
- {24, 0x0a, 244},
- {31, 0x0a, 244},
- {41, 0x0a, 244},
- {56, 0x0b, 244},
- },
- /* 216 */
- {
- {1, 0x0a, 245},
- {22, 0x0b, 245},
- {1, 0x0a, 246},
- {22, 0x0b, 246},
- {1, 0x0a, 247},
- {22, 0x0b, 247},
- {1, 0x0a, 248},
- {22, 0x0b, 248},
- {1, 0x0a, 250},
- {22, 0x0b, 250},
- {1, 0x0a, 251},
- {22, 0x0b, 251},
- {1, 0x0a, 252},
- {22, 0x0b, 252},
- {1, 0x0a, 253},
- {22, 0x0b, 253},
- },
- /* 217 */
- {
- {2, 0x0a, 245},
- {9, 0x0a, 245},
- {23, 0x0a, 245},
- {40, 0x0b, 245},
- {2, 0x0a, 246},
- {9, 0x0a, 246},
- {23, 0x0a, 246},
- {40, 0x0b, 246},
- {2, 0x0a, 247},
- {9, 0x0a, 247},
- {23, 0x0a, 247},
- {40, 0x0b, 247},
- {2, 0x0a, 248},
- {9, 0x0a, 248},
- {23, 0x0a, 248},
- {40, 0x0b, 248},
- },
- /* 218 */
- {
- {3, 0x0a, 245},
- {6, 0x0a, 245},
- {10, 0x0a, 245},
- {15, 0x0a, 245},
- {24, 0x0a, 245},
- {31, 0x0a, 245},
- {41, 0x0a, 245},
- {56, 0x0b, 245},
- {3, 0x0a, 246},
- {6, 0x0a, 246},
- {10, 0x0a, 246},
- {15, 0x0a, 246},
- {24, 0x0a, 246},
- {31, 0x0a, 246},
- {41, 0x0a, 246},
- {56, 0x0b, 246},
- },
- /* 219 */
- {
- {3, 0x0a, 247},
- {6, 0x0a, 247},
- {10, 0x0a, 247},
- {15, 0x0a, 247},
- {24, 0x0a, 247},
- {31, 0x0a, 247},
- {41, 0x0a, 247},
- {56, 0x0b, 247},
- {3, 0x0a, 248},
- {6, 0x0a, 248},
- {10, 0x0a, 248},
- {15, 0x0a, 248},
- {24, 0x0a, 248},
- {31, 0x0a, 248},
- {41, 0x0a, 248},
- {56, 0x0b, 248},
- },
- /* 220 */
- {
- {2, 0x0a, 250},
- {9, 0x0a, 250},
- {23, 0x0a, 250},
- {40, 0x0b, 250},
- {2, 0x0a, 251},
- {9, 0x0a, 251},
- {23, 0x0a, 251},
- {40, 0x0b, 251},
- {2, 0x0a, 252},
- {9, 0x0a, 252},
- {23, 0x0a, 252},
- {40, 0x0b, 252},
- {2, 0x0a, 253},
- {9, 0x0a, 253},
- {23, 0x0a, 253},
- {40, 0x0b, 253},
- },
- /* 221 */
- {
- {3, 0x0a, 250},
- {6, 0x0a, 250},
- {10, 0x0a, 250},
- {15, 0x0a, 250},
- {24, 0x0a, 250},
- {31, 0x0a, 250},
- {41, 0x0a, 250},
- {56, 0x0b, 250},
- {3, 0x0a, 251},
- {6, 0x0a, 251},
- {10, 0x0a, 251},
- {15, 0x0a, 251},
- {24, 0x0a, 251},
- {31, 0x0a, 251},
- {41, 0x0a, 251},
- {56, 0x0b, 251},
- },
- /* 222 */
- {
- {3, 0x0a, 252},
- {6, 0x0a, 252},
- {10, 0x0a, 252},
- {15, 0x0a, 252},
- {24, 0x0a, 252},
- {31, 0x0a, 252},
- {41, 0x0a, 252},
- {56, 0x0b, 252},
- {3, 0x0a, 253},
- {6, 0x0a, 253},
- {10, 0x0a, 253},
- {15, 0x0a, 253},
- {24, 0x0a, 253},
- {31, 0x0a, 253},
- {41, 0x0a, 253},
- {56, 0x0b, 253},
- },
- /* 223 */
- {
- {0, 0x0b, 254},
- {227, 0x00, 0},
- {229, 0x00, 0},
- {230, 0x00, 0},
- {233, 0x00, 0},
- {234, 0x00, 0},
- {236, 0x00, 0},
- {237, 0x00, 0},
- {241, 0x00, 0},
- {242, 0x00, 0},
- {244, 0x00, 0},
- {245, 0x00, 0},
- {248, 0x00, 0},
- {249, 0x00, 0},
- {251, 0x00, 0},
- {252, 0x00, 0},
- },
- /* 224 */
- {
- {1, 0x0a, 254},
- {22, 0x0b, 254},
- {0, 0x1b, 2},
- {0, 0x1b, 3},
- {0, 0x1b, 4},
- {0, 0x1b, 5},
- {0, 0x1b, 6},
- {0, 0x1b, 7},
- {0, 0x1b, 8},
- {0, 0x1b, 11},
- {0, 0x1b, 12},
- {0, 0x1b, 14},
- {0, 0x1b, 15},
- {0, 0x1b, 16},
- {0, 0x1b, 17},
- {0, 0x1b, 18},
- },
- /* 225 */
- {
- {2, 0x0a, 254},
- {9, 0x0a, 254},
- {23, 0x0a, 254},
- {40, 0x0b, 254},
- {1, 0x1a, 2},
- {22, 0x1b, 2},
- {1, 0x1a, 3},
- {22, 0x1b, 3},
- {1, 0x1a, 4},
- {22, 0x1b, 4},
- {1, 0x1a, 5},
- {22, 0x1b, 5},
- {1, 0x1a, 6},
- {22, 0x1b, 6},
- {1, 0x1a, 7},
- {22, 0x1b, 7},
- },
- /* 226 */
- {
- {3, 0x0a, 254},
- {6, 0x0a, 254},
- {10, 0x0a, 254},
- {15, 0x0a, 254},
- {24, 0x0a, 254},
- {31, 0x0a, 254},
- {41, 0x0a, 254},
- {56, 0x0b, 254},
- {2, 0x1a, 2},
- {9, 0x1a, 2},
- {23, 0x1a, 2},
- {40, 0x1b, 2},
- {2, 0x1a, 3},
- {9, 0x1a, 3},
- {23, 0x1a, 3},
- {40, 0x1b, 3},
- },
- /* 227 */
- {
- {3, 0x1a, 2},
- {6, 0x1a, 2},
- {10, 0x1a, 2},
- {15, 0x1a, 2},
- {24, 0x1a, 2},
- {31, 0x1a, 2},
- {41, 0x1a, 2},
- {56, 0x1b, 2},
- {3, 0x1a, 3},
- {6, 0x1a, 3},
- {10, 0x1a, 3},
- {15, 0x1a, 3},
- {24, 0x1a, 3},
- {31, 0x1a, 3},
- {41, 0x1a, 3},
- {56, 0x1b, 3},
- },
- /* 228 */
- {
- {2, 0x1a, 4},
- {9, 0x1a, 4},
- {23, 0x1a, 4},
- {40, 0x1b, 4},
- {2, 0x1a, 5},
- {9, 0x1a, 5},
- {23, 0x1a, 5},
- {40, 0x1b, 5},
- {2, 0x1a, 6},
- {9, 0x1a, 6},
- {23, 0x1a, 6},
- {40, 0x1b, 6},
- {2, 0x1a, 7},
- {9, 0x1a, 7},
- {23, 0x1a, 7},
- {40, 0x1b, 7},
- },
- /* 229 */
- {
- {3, 0x1a, 4},
- {6, 0x1a, 4},
- {10, 0x1a, 4},
- {15, 0x1a, 4},
- {24, 0x1a, 4},
- {31, 0x1a, 4},
- {41, 0x1a, 4},
- {56, 0x1b, 4},
- {3, 0x1a, 5},
- {6, 0x1a, 5},
- {10, 0x1a, 5},
- {15, 0x1a, 5},
- {24, 0x1a, 5},
- {31, 0x1a, 5},
- {41, 0x1a, 5},
- {56, 0x1b, 5},
- },
- /* 230 */
- {
- {3, 0x1a, 6},
- {6, 0x1a, 6},
- {10, 0x1a, 6},
- {15, 0x1a, 6},
- {24, 0x1a, 6},
- {31, 0x1a, 6},
- {41, 0x1a, 6},
- {56, 0x1b, 6},
- {3, 0x1a, 7},
- {6, 0x1a, 7},
- {10, 0x1a, 7},
- {15, 0x1a, 7},
- {24, 0x1a, 7},
- {31, 0x1a, 7},
- {41, 0x1a, 7},
- {56, 0x1b, 7},
- },
- /* 231 */
- {
- {1, 0x1a, 8},
- {22, 0x1b, 8},
- {1, 0x1a, 11},
- {22, 0x1b, 11},
- {1, 0x1a, 12},
- {22, 0x1b, 12},
- {1, 0x1a, 14},
- {22, 0x1b, 14},
- {1, 0x1a, 15},
- {22, 0x1b, 15},
- {1, 0x1a, 16},
- {22, 0x1b, 16},
- {1, 0x1a, 17},
- {22, 0x1b, 17},
- {1, 0x1a, 18},
- {22, 0x1b, 18},
- },
- /* 232 */
- {
- {2, 0x1a, 8},
- {9, 0x1a, 8},
- {23, 0x1a, 8},
- {40, 0x1b, 8},
- {2, 0x1a, 11},
- {9, 0x1a, 11},
- {23, 0x1a, 11},
- {40, 0x1b, 11},
- {2, 0x1a, 12},
- {9, 0x1a, 12},
- {23, 0x1a, 12},
- {40, 0x1b, 12},
- {2, 0x1a, 14},
- {9, 0x1a, 14},
- {23, 0x1a, 14},
- {40, 0x1b, 14},
- },
- /* 233 */
- {
- {3, 0x1a, 8},
- {6, 0x1a, 8},
- {10, 0x1a, 8},
- {15, 0x1a, 8},
- {24, 0x1a, 8},
- {31, 0x1a, 8},
- {41, 0x1a, 8},
- {56, 0x1b, 8},
- {3, 0x1a, 11},
- {6, 0x1a, 11},
- {10, 0x1a, 11},
- {15, 0x1a, 11},
- {24, 0x1a, 11},
- {31, 0x1a, 11},
- {41, 0x1a, 11},
- {56, 0x1b, 11},
- },
- /* 234 */
- {
- {3, 0x1a, 12},
- {6, 0x1a, 12},
- {10, 0x1a, 12},
- {15, 0x1a, 12},
- {24, 0x1a, 12},
- {31, 0x1a, 12},
- {41, 0x1a, 12},
- {56, 0x1b, 12},
- {3, 0x1a, 14},
- {6, 0x1a, 14},
- {10, 0x1a, 14},
- {15, 0x1a, 14},
- {24, 0x1a, 14},
- {31, 0x1a, 14},
- {41, 0x1a, 14},
- {56, 0x1b, 14},
- },
- /* 235 */
- {
- {2, 0x1a, 15},
- {9, 0x1a, 15},
- {23, 0x1a, 15},
- {40, 0x1b, 15},
- {2, 0x1a, 16},
- {9, 0x1a, 16},
- {23, 0x1a, 16},
- {40, 0x1b, 16},
- {2, 0x1a, 17},
- {9, 0x1a, 17},
- {23, 0x1a, 17},
- {40, 0x1b, 17},
- {2, 0x1a, 18},
- {9, 0x1a, 18},
- {23, 0x1a, 18},
- {40, 0x1b, 18},
- },
- /* 236 */
- {
- {3, 0x1a, 15},
- {6, 0x1a, 15},
- {10, 0x1a, 15},
- {15, 0x1a, 15},
- {24, 0x1a, 15},
- {31, 0x1a, 15},
- {41, 0x1a, 15},
- {56, 0x1b, 15},
- {3, 0x1a, 16},
- {6, 0x1a, 16},
- {10, 0x1a, 16},
- {15, 0x1a, 16},
- {24, 0x1a, 16},
- {31, 0x1a, 16},
- {41, 0x1a, 16},
- {56, 0x1b, 16},
- },
- /* 237 */
- {
- {3, 0x1a, 17},
- {6, 0x1a, 17},
- {10, 0x1a, 17},
- {15, 0x1a, 17},
- {24, 0x1a, 17},
- {31, 0x1a, 17},
- {41, 0x1a, 17},
- {56, 0x1b, 17},
- {3, 0x1a, 18},
- {6, 0x1a, 18},
- {10, 0x1a, 18},
- {15, 0x1a, 18},
- {24, 0x1a, 18},
- {31, 0x1a, 18},
- {41, 0x1a, 18},
- {56, 0x1b, 18},
- },
- /* 238 */
- {
- {0, 0x1b, 19},
- {0, 0x1b, 20},
- {0, 0x1b, 21},
- {0, 0x1b, 23},
- {0, 0x1b, 24},
- {0, 0x1b, 25},
- {0, 0x1b, 26},
- {0, 0x1b, 27},
- {0, 0x1b, 28},
- {0, 0x1b, 29},
- {0, 0x1b, 30},
- {0, 0x1b, 31},
- {0, 0x1b, 127},
- {0, 0x0b, 220},
- {0, 0x0b, 249},
- {253, 0x00, 0},
- },
- /* 239 */
- {
- {1, 0x1a, 19},
- {22, 0x1b, 19},
- {1, 0x1a, 20},
- {22, 0x1b, 20},
- {1, 0x1a, 21},
- {22, 0x1b, 21},
- {1, 0x1a, 23},
- {22, 0x1b, 23},
- {1, 0x1a, 24},
- {22, 0x1b, 24},
- {1, 0x1a, 25},
- {22, 0x1b, 25},
- {1, 0x1a, 26},
- {22, 0x1b, 26},
- {1, 0x1a, 27},
- {22, 0x1b, 27},
- },
- /* 240 */
- {
- {2, 0x1a, 19},
- {9, 0x1a, 19},
- {23, 0x1a, 19},
- {40, 0x1b, 19},
- {2, 0x1a, 20},
- {9, 0x1a, 20},
- {23, 0x1a, 20},
- {40, 0x1b, 20},
- {2, 0x1a, 21},
- {9, 0x1a, 21},
- {23, 0x1a, 21},
- {40, 0x1b, 21},
- {2, 0x1a, 23},
- {9, 0x1a, 23},
- {23, 0x1a, 23},
- {40, 0x1b, 23},
- },
- /* 241 */
- {
- {3, 0x1a, 19},
- {6, 0x1a, 19},
- {10, 0x1a, 19},
- {15, 0x1a, 19},
- {24, 0x1a, 19},
- {31, 0x1a, 19},
- {41, 0x1a, 19},
- {56, 0x1b, 19},
- {3, 0x1a, 20},
- {6, 0x1a, 20},
- {10, 0x1a, 20},
- {15, 0x1a, 20},
- {24, 0x1a, 20},
- {31, 0x1a, 20},
- {41, 0x1a, 20},
- {56, 0x1b, 20},
- },
- /* 242 */
- {
- {3, 0x1a, 21},
- {6, 0x1a, 21},
- {10, 0x1a, 21},
- {15, 0x1a, 21},
- {24, 0x1a, 21},
- {31, 0x1a, 21},
- {41, 0x1a, 21},
- {56, 0x1b, 21},
- {3, 0x1a, 23},
- {6, 0x1a, 23},
- {10, 0x1a, 23},
- {15, 0x1a, 23},
- {24, 0x1a, 23},
- {31, 0x1a, 23},
- {41, 0x1a, 23},
- {56, 0x1b, 23},
- },
- /* 243 */
- {
- {2, 0x1a, 24},
- {9, 0x1a, 24},
- {23, 0x1a, 24},
- {40, 0x1b, 24},
- {2, 0x1a, 25},
- {9, 0x1a, 25},
- {23, 0x1a, 25},
- {40, 0x1b, 25},
- {2, 0x1a, 26},
- {9, 0x1a, 26},
- {23, 0x1a, 26},
- {40, 0x1b, 26},
- {2, 0x1a, 27},
- {9, 0x1a, 27},
- {23, 0x1a, 27},
- {40, 0x1b, 27},
- },
- /* 244 */
- {
- {3, 0x1a, 24},
- {6, 0x1a, 24},
- {10, 0x1a, 24},
- {15, 0x1a, 24},
- {24, 0x1a, 24},
- {31, 0x1a, 24},
- {41, 0x1a, 24},
- {56, 0x1b, 24},
- {3, 0x1a, 25},
- {6, 0x1a, 25},
- {10, 0x1a, 25},
- {15, 0x1a, 25},
- {24, 0x1a, 25},
- {31, 0x1a, 25},
- {41, 0x1a, 25},
- {56, 0x1b, 25},
- },
- /* 245 */
- {
- {3, 0x1a, 26},
- {6, 0x1a, 26},
- {10, 0x1a, 26},
- {15, 0x1a, 26},
- {24, 0x1a, 26},
- {31, 0x1a, 26},
- {41, 0x1a, 26},
- {56, 0x1b, 26},
- {3, 0x1a, 27},
- {6, 0x1a, 27},
- {10, 0x1a, 27},
- {15, 0x1a, 27},
- {24, 0x1a, 27},
- {31, 0x1a, 27},
- {41, 0x1a, 27},
- {56, 0x1b, 27},
- },
- /* 246 */
- {
- {1, 0x1a, 28},
- {22, 0x1b, 28},
- {1, 0x1a, 29},
- {22, 0x1b, 29},
- {1, 0x1a, 30},
- {22, 0x1b, 30},
- {1, 0x1a, 31},
- {22, 0x1b, 31},
- {1, 0x1a, 127},
- {22, 0x1b, 127},
- {1, 0x0a, 220},
- {22, 0x0b, 220},
- {1, 0x0a, 249},
- {22, 0x0b, 249},
- {254, 0x00, 0},
- {255, 0x00, 0},
- },
- /* 247 */
- {
- {2, 0x1a, 28},
- {9, 0x1a, 28},
- {23, 0x1a, 28},
- {40, 0x1b, 28},
- {2, 0x1a, 29},
- {9, 0x1a, 29},
- {23, 0x1a, 29},
- {40, 0x1b, 29},
- {2, 0x1a, 30},
- {9, 0x1a, 30},
- {23, 0x1a, 30},
- {40, 0x1b, 30},
- {2, 0x1a, 31},
- {9, 0x1a, 31},
- {23, 0x1a, 31},
- {40, 0x1b, 31},
- },
- /* 248 */
- {
- {3, 0x1a, 28},
- {6, 0x1a, 28},
- {10, 0x1a, 28},
- {15, 0x1a, 28},
- {24, 0x1a, 28},
- {31, 0x1a, 28},
- {41, 0x1a, 28},
- {56, 0x1b, 28},
- {3, 0x1a, 29},
- {6, 0x1a, 29},
- {10, 0x1a, 29},
- {15, 0x1a, 29},
- {24, 0x1a, 29},
- {31, 0x1a, 29},
- {41, 0x1a, 29},
- {56, 0x1b, 29},
- },
- /* 249 */
- {
- {3, 0x1a, 30},
- {6, 0x1a, 30},
- {10, 0x1a, 30},
- {15, 0x1a, 30},
- {24, 0x1a, 30},
- {31, 0x1a, 30},
- {41, 0x1a, 30},
- {56, 0x1b, 30},
- {3, 0x1a, 31},
- {6, 0x1a, 31},
- {10, 0x1a, 31},
- {15, 0x1a, 31},
- {24, 0x1a, 31},
- {31, 0x1a, 31},
- {41, 0x1a, 31},
- {56, 0x1b, 31},
- },
- /* 250 */
- {
- {2, 0x1a, 127},
- {9, 0x1a, 127},
- {23, 0x1a, 127},
- {40, 0x1b, 127},
- {2, 0x0a, 220},
- {9, 0x0a, 220},
- {23, 0x0a, 220},
- {40, 0x0b, 220},
- {2, 0x0a, 249},
- {9, 0x0a, 249},
- {23, 0x0a, 249},
- {40, 0x0b, 249},
- {0, 0x1b, 10},
- {0, 0x1b, 13},
- {0, 0x1b, 22},
- {0, 0x04, 0},
- },
- /* 251 */
- {
- {3, 0x1a, 127},
- {6, 0x1a, 127},
- {10, 0x1a, 127},
- {15, 0x1a, 127},
- {24, 0x1a, 127},
- {31, 0x1a, 127},
- {41, 0x1a, 127},
- {56, 0x1b, 127},
- {3, 0x0a, 220},
- {6, 0x0a, 220},
- {10, 0x0a, 220},
- {15, 0x0a, 220},
- {24, 0x0a, 220},
- {31, 0x0a, 220},
- {41, 0x0a, 220},
- {56, 0x0b, 220},
- },
- /* 252 */
- {
- {3, 0x0a, 249},
- {6, 0x0a, 249},
- {10, 0x0a, 249},
- {15, 0x0a, 249},
- {24, 0x0a, 249},
- {31, 0x0a, 249},
- {41, 0x0a, 249},
- {56, 0x0b, 249},
- {1, 0x1a, 10},
- {22, 0x1b, 10},
- {1, 0x1a, 13},
- {22, 0x1b, 13},
- {1, 0x1a, 22},
- {22, 0x1b, 22},
- {0, 0x04, 0},
- {0, 0x04, 0},
- },
- /* 253 */
- {
- {2, 0x1a, 10},
- {9, 0x1a, 10},
- {23, 0x1a, 10},
- {40, 0x1b, 10},
- {2, 0x1a, 13},
- {9, 0x1a, 13},
- {23, 0x1a, 13},
- {40, 0x1b, 13},
- {2, 0x1a, 22},
- {9, 0x1a, 22},
- {23, 0x1a, 22},
- {40, 0x1b, 22},
- {0, 0x04, 0},
- {0, 0x04, 0},
- {0, 0x04, 0},
- {0, 0x04, 0},
- },
- /* 254 */
- {
- {3, 0x1a, 10},
- {6, 0x1a, 10},
- {10, 0x1a, 10},
- {15, 0x1a, 10},
- {24, 0x1a, 10},
- {31, 0x1a, 10},
- {41, 0x1a, 10},
- {56, 0x1b, 10},
- {3, 0x1a, 13},
- {6, 0x1a, 13},
- {10, 0x1a, 13},
- {15, 0x1a, 13},
- {24, 0x1a, 13},
- {31, 0x1a, 13},
- {41, 0x1a, 13},
- {56, 0x1b, 13},
- },
- /* 255 */
- {
- {3, 0x1a, 22},
- {6, 0x1a, 22},
- {10, 0x1a, 22},
- {15, 0x1a, 22},
- {24, 0x1a, 22},
- {31, 0x1a, 22},
- {41, 0x1a, 22},
- {56, 0x1b, 22},
- {0, 0x04, 0},
- {0, 0x04, 0},
- {0, 0x04, 0},
- {0, 0x04, 0},
- {0, 0x04, 0},
- {0, 0x04, 0},
- {0, 0x04, 0},
- {0, 0x04, 0},
- },
-};
diff --git a/web/server/h2o/libh2o/lib/http2/hpack_static_table.h b/web/server/h2o/libh2o/lib/http2/hpack_static_table.h
deleted file mode 100644
index 4c1243103..000000000
--- a/web/server/h2o/libh2o/lib/http2/hpack_static_table.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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 &quot;Software&quot;), 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 &quot;AS IS&quot;, 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.
- */
-
-/* automatically generated by tokens.pl */
-
-static const struct st_h2o_hpack_static_table_entry_t h2o_hpack_static_table[61] = {
- { H2O_TOKEN_AUTHORITY, { H2O_STRLIT("") } },
- { H2O_TOKEN_METHOD, { H2O_STRLIT("GET") } },
- { H2O_TOKEN_METHOD, { H2O_STRLIT("POST") } },
- { H2O_TOKEN_PATH, { H2O_STRLIT("/") } },
- { H2O_TOKEN_PATH, { H2O_STRLIT("/index.html") } },
- { H2O_TOKEN_SCHEME, { H2O_STRLIT("http") } },
- { H2O_TOKEN_SCHEME, { H2O_STRLIT("https") } },
- { H2O_TOKEN_STATUS, { H2O_STRLIT("200") } },
- { H2O_TOKEN_STATUS, { H2O_STRLIT("204") } },
- { H2O_TOKEN_STATUS, { H2O_STRLIT("206") } },
- { H2O_TOKEN_STATUS, { H2O_STRLIT("304") } },
- { H2O_TOKEN_STATUS, { H2O_STRLIT("400") } },
- { H2O_TOKEN_STATUS, { H2O_STRLIT("404") } },
- { H2O_TOKEN_STATUS, { H2O_STRLIT("500") } },
- { H2O_TOKEN_ACCEPT_CHARSET, { H2O_STRLIT("") } },
- { H2O_TOKEN_ACCEPT_ENCODING, { H2O_STRLIT("gzip, deflate") } },
- { H2O_TOKEN_ACCEPT_LANGUAGE, { H2O_STRLIT("") } },
- { H2O_TOKEN_ACCEPT_RANGES, { H2O_STRLIT("") } },
- { H2O_TOKEN_ACCEPT, { H2O_STRLIT("") } },
- { H2O_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN, { H2O_STRLIT("") } },
- { H2O_TOKEN_AGE, { H2O_STRLIT("") } },
- { H2O_TOKEN_ALLOW, { H2O_STRLIT("") } },
- { H2O_TOKEN_AUTHORIZATION, { H2O_STRLIT("") } },
- { H2O_TOKEN_CACHE_CONTROL, { H2O_STRLIT("") } },
- { H2O_TOKEN_CONTENT_DISPOSITION, { H2O_STRLIT("") } },
- { H2O_TOKEN_CONTENT_ENCODING, { H2O_STRLIT("") } },
- { H2O_TOKEN_CONTENT_LANGUAGE, { H2O_STRLIT("") } },
- { H2O_TOKEN_CONTENT_LENGTH, { H2O_STRLIT("") } },
- { H2O_TOKEN_CONTENT_LOCATION, { H2O_STRLIT("") } },
- { H2O_TOKEN_CONTENT_RANGE, { H2O_STRLIT("") } },
- { H2O_TOKEN_CONTENT_TYPE, { H2O_STRLIT("") } },
- { H2O_TOKEN_COOKIE, { H2O_STRLIT("") } },
- { H2O_TOKEN_DATE, { H2O_STRLIT("") } },
- { H2O_TOKEN_ETAG, { H2O_STRLIT("") } },
- { H2O_TOKEN_EXPECT, { H2O_STRLIT("") } },
- { H2O_TOKEN_EXPIRES, { H2O_STRLIT("") } },
- { H2O_TOKEN_FROM, { H2O_STRLIT("") } },
- { H2O_TOKEN_HOST, { H2O_STRLIT("") } },
- { H2O_TOKEN_IF_MATCH, { H2O_STRLIT("") } },
- { H2O_TOKEN_IF_MODIFIED_SINCE, { H2O_STRLIT("") } },
- { H2O_TOKEN_IF_NONE_MATCH, { H2O_STRLIT("") } },
- { H2O_TOKEN_IF_RANGE, { H2O_STRLIT("") } },
- { H2O_TOKEN_IF_UNMODIFIED_SINCE, { H2O_STRLIT("") } },
- { H2O_TOKEN_LAST_MODIFIED, { H2O_STRLIT("") } },
- { H2O_TOKEN_LINK, { H2O_STRLIT("") } },
- { H2O_TOKEN_LOCATION, { H2O_STRLIT("") } },
- { H2O_TOKEN_MAX_FORWARDS, { H2O_STRLIT("") } },
- { H2O_TOKEN_PROXY_AUTHENTICATE, { H2O_STRLIT("") } },
- { H2O_TOKEN_PROXY_AUTHORIZATION, { H2O_STRLIT("") } },
- { H2O_TOKEN_RANGE, { H2O_STRLIT("") } },
- { H2O_TOKEN_REFERER, { H2O_STRLIT("") } },
- { H2O_TOKEN_REFRESH, { H2O_STRLIT("") } },
- { H2O_TOKEN_RETRY_AFTER, { H2O_STRLIT("") } },
- { H2O_TOKEN_SERVER, { H2O_STRLIT("") } },
- { H2O_TOKEN_SET_COOKIE, { H2O_STRLIT("") } },
- { H2O_TOKEN_STRICT_TRANSPORT_SECURITY, { H2O_STRLIT("") } },
- { H2O_TOKEN_TRANSFER_ENCODING, { H2O_STRLIT("") } },
- { H2O_TOKEN_USER_AGENT, { H2O_STRLIT("") } },
- { H2O_TOKEN_VARY, { H2O_STRLIT("") } },
- { H2O_TOKEN_VIA, { H2O_STRLIT("") } },
- { H2O_TOKEN_WWW_AUTHENTICATE, { H2O_STRLIT("") } }
-};
diff --git a/web/server/h2o/libh2o/lib/http2/http2_debug_state.c b/web/server/h2o/libh2o/lib/http2/http2_debug_state.c
deleted file mode 100644
index 3ef8de37f..000000000
--- a/web/server/h2o/libh2o/lib/http2/http2_debug_state.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (c) 2016 DeNA Co., Ltd., Ichito Nagata
- *
- * 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 <inttypes.h>
-#include "h2o.h"
-#include "h2o/http2.h"
-#include "h2o/http2_internal.h"
-
-static const char *debug_state_string_open = "OPEN";
-static const char *debug_state_string_half_closed_remote = "HALF_CLOSED_REMOTE";
-static const char *debug_state_string_reserved_local = "RESERVED_LOCAL";
-
-static const char *get_debug_state_string(h2o_http2_stream_t *stream)
-{
- if (h2o_http2_stream_is_push(stream->stream_id)) {
- switch (stream->state) {
- case H2O_HTTP2_STREAM_STATE_RECV_HEADERS:
- case H2O_HTTP2_STREAM_STATE_RECV_BODY:
- case H2O_HTTP2_STREAM_STATE_REQ_PENDING:
- return debug_state_string_reserved_local;
- case H2O_HTTP2_STREAM_STATE_SEND_HEADERS:
- case H2O_HTTP2_STREAM_STATE_SEND_BODY:
- case H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL:
- return debug_state_string_half_closed_remote;
- case H2O_HTTP2_STREAM_STATE_IDLE:
- case H2O_HTTP2_STREAM_STATE_END_STREAM:
- return NULL;
- }
- } else {
- switch (stream->state) {
- case H2O_HTTP2_STREAM_STATE_RECV_HEADERS:
- case H2O_HTTP2_STREAM_STATE_RECV_BODY:
- return debug_state_string_open;
- case H2O_HTTP2_STREAM_STATE_REQ_PENDING:
- case H2O_HTTP2_STREAM_STATE_SEND_HEADERS:
- case H2O_HTTP2_STREAM_STATE_SEND_BODY:
- case H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL:
- return debug_state_string_half_closed_remote;
- case H2O_HTTP2_STREAM_STATE_IDLE:
- case H2O_HTTP2_STREAM_STATE_END_STREAM:
- return NULL;
- }
- }
- return NULL;
-}
-
-__attribute__((format(printf, 3, 4))) static void append_chunk(h2o_mem_pool_t *pool, h2o_iovec_vector_t *chunks, const char *fmt,
- ...)
-{
- va_list args;
-
- va_start(args, fmt);
- int size = vsnprintf(NULL, 0, fmt, args);
- va_end(args);
-
- assert(size > 0);
-
- h2o_iovec_t v;
- v.base = h2o_mem_alloc_pool(pool, size + 1);
-
- va_start(args, fmt);
- v.len = vsnprintf(v.base, size + 1, fmt, args);
- va_end(args);
-
- h2o_vector_reserve(pool, chunks, chunks->size + 1);
- chunks->entries[chunks->size++] = v;
-}
-
-static void append_header_table_chunks(h2o_mem_pool_t *pool, h2o_iovec_vector_t *chunks, h2o_hpack_header_table_t *header_table)
-{
- int i;
- for (i = 0; i < header_table->num_entries; i++) {
- h2o_hpack_header_table_entry_t *entry = h2o_hpack_header_table_get(header_table, i);
- append_chunk(pool, chunks, "\n"
- " [ \"%.*s\", \"%.*s\" ],",
- (int)entry->name->len, entry->name->base, (int)entry->value->len, entry->value->base);
- }
-
- if (i > 0) {
- // remove the last commna
- --chunks->entries[chunks->size - 1].len;
- }
-}
-
-h2o_http2_debug_state_t *h2o_http2_get_debug_state(h2o_req_t *req, int hpack_enabled)
-{
- h2o_http2_conn_t *conn = (h2o_http2_conn_t *)req->conn;
- h2o_http2_debug_state_t *state = h2o_mem_alloc_pool(&req->pool, sizeof(*state));
- *state = (h2o_http2_debug_state_t){{NULL}};
-
- state->conn_flow_in = conn->_write.window._avail;
- state->conn_flow_out = conn->_write.window._avail;
-
- append_chunk(&req->pool, &state->json, "{\n"
- " \"version\": \"draft-01\",\n"
- " \"settings\": {\n"
- " \"SETTINGS_HEADER_TABLE_SIZE\": %" PRIu32 ",\n"
- " \"SETTINGS_ENABLE_PUSH\": %" PRIu32 ",\n"
- " \"SETTINGS_MAX_CONCURRENT_STREAMS\": %" PRIu32 ",\n"
- " \"SETTINGS_INITIAL_WINDOW_SIZE\": %" PRIu32 ",\n"
- " \"SETTINGS_MAX_FRAME_SIZE\": %" PRIu32 "\n"
- " },\n"
- " \"peerSettings\": {\n"
- " \"SETTINGS_HEADER_TABLE_SIZE\": %" PRIu32 ",\n"
- " \"SETTINGS_ENABLE_PUSH\": %" PRIu32 ",\n"
- " \"SETTINGS_MAX_CONCURRENT_STREAMS\": %" PRIu32 ",\n"
- " \"SETTINGS_INITIAL_WINDOW_SIZE\": %" PRIu32 ",\n"
- " \"SETTINGS_MAX_FRAME_SIZE\": %" PRIu32 "\n"
- " },\n"
- " \"connFlowIn\": %zd,\n"
- " \"connFlowOut\": %zd,\n"
- " \"streams\": {",
- H2O_HTTP2_SETTINGS_HOST.header_table_size, H2O_HTTP2_SETTINGS_HOST.enable_push,
- H2O_HTTP2_SETTINGS_HOST.max_concurrent_streams, H2O_HTTP2_SETTINGS_HOST.initial_window_size,
- H2O_HTTP2_SETTINGS_HOST.max_frame_size, conn->peer_settings.header_table_size, conn->peer_settings.enable_push,
- conn->peer_settings.max_concurrent_streams, conn->peer_settings.initial_window_size,
- conn->peer_settings.max_frame_size, conn->_input_window._avail, conn->_write.window._avail);
-
- /* encode streams */
- {
- h2o_http2_stream_t *stream;
- kh_foreach_value(conn->streams, stream, {
- const char *state_string = get_debug_state_string(stream);
- if (state_string == NULL)
- continue;
-
- append_chunk(&req->pool, &state->json, "\n"
- " \"%" PRIu32 "\": {\n"
- " \"state\": \"%s\",\n"
- " \"flowIn\": %zd,\n"
- " \"flowOut\": %zd,\n"
- " \"dataIn\": %zu,\n"
- " \"dataOut\": %zu,\n"
- " \"created\": %" PRIu64 "\n"
- " },",
- stream->stream_id, state_string, stream->input_window._avail, stream->output_window._avail,
- (stream->_req_body == NULL ? 0 : stream->_req_body->size), stream->req.bytes_sent,
- (uint64_t)stream->req.timestamps.request_begin_at.tv_sec);
- });
-
- if (conn->streams->size > 0) {
- // remove the last commna
- --state->json.entries[state->json.size - 1].len;
- }
- }
-
- append_chunk(&req->pool, &state->json, "\n"
- " }");
-
- if (hpack_enabled) {
- /* encode inbound header table */
- append_chunk(&req->pool, &state->json, ",\n"
- " \"hpack\": {\n"
- " \"inboundTableSize\": %zd,\n"
- " \"inboundDynamicHeaderTable\": [",
- conn->_input_header_table.num_entries);
- append_header_table_chunks(&req->pool, &state->json, &conn->_input_header_table);
-
- /* encode outbound header table */
- append_chunk(&req->pool, &state->json, "\n"
- " ],\n"
- " \"outboundTableSize\": %zd,\n"
- " \"outboundDynamicHeaderTable\": [",
- conn->_output_header_table.num_entries);
- append_header_table_chunks(&req->pool, &state->json, &conn->_output_header_table);
-
- append_chunk(&req->pool, &state->json, "\n"
- " ]\n"
- " }");
- }
-
- append_chunk(&req->pool, &state->json, "\n"
- "}\n");
-
- return state;
-}
diff --git a/web/server/h2o/libh2o/lib/http2/scheduler.c b/web/server/h2o/libh2o/lib/http2/scheduler.c
deleted file mode 100644
index 0ea7e4591..000000000
--- a/web/server/h2o/libh2o/lib/http2/scheduler.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (c) 2015 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 "h2o.h"
-#include "h2o/http2_scheduler.h"
-
-struct st_h2o_http2_scheduler_queue_t {
- uint64_t bits;
- size_t offset;
- h2o_linklist_t anchors[64];
- h2o_linklist_t anchor257;
-};
-
-static void queue_init(h2o_http2_scheduler_queue_t *queue)
-{
- size_t i;
- queue->bits = 0;
- queue->offset = 0;
- for (i = 0; i != sizeof(queue->anchors) / sizeof(queue->anchors[0]); ++i)
- h2o_linklist_init_anchor(queue->anchors + i);
- h2o_linklist_init_anchor(&queue->anchor257);
-}
-
-static int queue_is_empty(h2o_http2_scheduler_queue_t *queue)
-{
- return queue->bits == 0 && h2o_linklist_is_empty(&queue->anchor257);
-}
-
-static void queue_set(h2o_http2_scheduler_queue_t *queue, h2o_http2_scheduler_queue_node_t *node, uint16_t weight)
-{
- /* holds 257 entries of offsets (multiplied by 65536) where nodes with weights between 1..257 should go into
- * each entry (expect for weight=256) is calculated as: round(N / weight), where N is adjusted so that the
- * value would become 63*65536 for weight=0.
- * weight=257 is used internally to send data before any of the streams being pulled, and therefore has the offset set to zero.
- */
- static const unsigned OFFSET_TABLE[] = {
- 4128768, 2064384, 1376256, 1032192, 825754, 688128, 589824, 516096, 458752, 412877, 375343, 344064, 317598, 294912, 275251,
- 258048, 242869, 229376, 217304, 206438, 196608, 187671, 179512, 172032, 165151, 158799, 152917, 147456, 142371, 137626,
- 133186, 129024, 125114, 121434, 117965, 114688, 111588, 108652, 105866, 103219, 100702, 98304, 96018, 93836, 91750,
- 89756, 87846, 86016, 84261, 82575, 80956, 79399, 77901, 76459, 75069, 73728, 72435, 71186, 69979, 68813,
- 67685, 66593, 65536, 64512, 63520, 62557, 61623, 60717, 59837, 58982, 58152, 57344, 56558, 55794, 55050,
- 54326, 53620, 52933, 52263, 51610, 50972, 50351, 49744, 49152, 48574, 48009, 47457, 46918, 46391, 45875,
- 45371, 44878, 44395, 43923, 43461, 43008, 42565, 42130, 41705, 41288, 40879, 40478, 40085, 39700, 39322,
- 38951, 38587, 38229, 37879, 37534, 37196, 36864, 36538, 36217, 35902, 35593, 35289, 34990, 34696, 34406,
- 34122, 33842, 33567, 33297, 33030, 32768, 32510, 32256, 32006, 31760, 31517, 31279, 31043, 30812, 30583,
- 30359, 30137, 29919, 29703, 29491, 29282, 29076, 28873, 28672, 28474, 28279, 28087, 27897, 27710, 27525,
- 27343, 27163, 26985, 26810, 26637, 26466, 26298, 26131, 25967, 25805, 25645, 25486, 25330, 25175, 25023,
- 24872, 24723, 24576, 24431, 24287, 24145, 24004, 23866, 23729, 23593, 23459, 23326, 23195, 23066, 22938,
- 22811, 22686, 22562, 22439, 22318, 22198, 22079, 21962, 21845, 21730, 21617, 21504, 21393, 21282, 21173,
- 21065, 20958, 20852, 20748, 20644, 20541, 20439, 20339, 20239, 20140, 20043, 19946, 19850, 19755, 19661,
- 19568, 19475, 19384, 19293, 19204, 19115, 19027, 18939, 18853, 18767, 18682, 18598, 18515, 18432, 18350,
- 18269, 18188, 18109, 18030, 17951, 17873, 17796, 17720, 17644, 17569, 17495, 17421, 17348, 17275, 17203,
- 17132, 17061, 16991, 16921, 16852, 16784, 16716, 16648, 16581, 16515, 16449, 16384, 16319, 16255, 16191,
- 16128, 0};
-
- assert(!h2o_linklist_is_linked(&node->_link));
-
- if (weight > 256) {
-
- h2o_linklist_insert(&queue->anchor257, &node->_link);
-
- } else {
-
- assert(1 <= weight);
-
- size_t offset = OFFSET_TABLE[weight - 1] + node->_deficit;
- node->_deficit = offset % 65536;
- offset = offset / 65536;
-
- queue->bits |= 1ULL << (sizeof(queue->bits) * 8 - 1 - offset);
- h2o_linklist_insert(queue->anchors + (queue->offset + offset) % (sizeof(queue->anchors) / sizeof(queue->anchors[0])),
- &node->_link);
- }
-}
-
-static void queue_unset(h2o_http2_scheduler_queue_node_t *node)
-{
- assert(h2o_linklist_is_linked(&node->_link));
- h2o_linklist_unlink(&node->_link);
-}
-
-static h2o_http2_scheduler_queue_node_t *queue_pop(h2o_http2_scheduler_queue_t *queue)
-{
- if (!h2o_linklist_is_empty(&queue->anchor257)) {
- h2o_http2_scheduler_queue_node_t *node =
- H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_queue_node_t, _link, queue->anchor257.next);
- h2o_linklist_unlink(&node->_link);
- return node;
- }
-
- while (queue->bits != 0) {
- int zeroes = __builtin_clzll(queue->bits);
- queue->bits <<= zeroes;
- queue->offset = (queue->offset + zeroes) % (sizeof(queue->anchors) / sizeof(queue->anchors[0]));
- if (!h2o_linklist_is_empty(queue->anchors + queue->offset)) {
- h2o_http2_scheduler_queue_node_t *node =
- H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_queue_node_t, _link, queue->anchors[queue->offset].next);
- h2o_linklist_unlink(&node->_link);
- if (h2o_linklist_is_empty(queue->anchors + queue->offset))
- queue->bits &= (1ULL << (sizeof(queue->bits) * 8 - 1)) - 1;
- return node;
- }
- queue->bits &= (1ULL << (sizeof(queue->bits) * 8 - 1)) - 1;
- }
- return NULL;
-}
-
-static void init_node(h2o_http2_scheduler_node_t *node, h2o_http2_scheduler_node_t *parent)
-{
- *node = (h2o_http2_scheduler_node_t){parent};
- h2o_linklist_init_anchor(&node->_all_refs);
-}
-
-static h2o_http2_scheduler_queue_t *get_queue(h2o_http2_scheduler_node_t *node)
-{
- if (node->_queue == NULL) {
- node->_queue = h2o_mem_alloc(sizeof(*node->_queue));
- queue_init(node->_queue);
- }
- return node->_queue;
-}
-
-static void incr_active_cnt(h2o_http2_scheduler_node_t *node)
-{
- h2o_http2_scheduler_openref_t *ref;
-
- /* do nothing if node is the root */
- if (node->_parent == NULL)
- return;
-
- ref = (h2o_http2_scheduler_openref_t *)node;
- if (++ref->_active_cnt != 1)
- return;
- /* just changed to active */
- queue_set(get_queue(ref->node._parent), &ref->_queue_node, ref->weight);
- /* delegate the change towards root */
- incr_active_cnt(ref->node._parent);
-}
-
-static void decr_active_cnt(h2o_http2_scheduler_node_t *node)
-{
- h2o_http2_scheduler_openref_t *ref;
-
- /* do notnig if node is the root */
- if (node->_parent == NULL)
- return;
-
- ref = (h2o_http2_scheduler_openref_t *)node;
- if (--ref->_active_cnt != 0)
- return;
- /* just changed to inactive */
- queue_unset(&ref->_queue_node);
- /* delegate the change towards root */
- decr_active_cnt(ref->node._parent);
-}
-
-static void convert_to_exclusive(h2o_http2_scheduler_node_t *parent, h2o_http2_scheduler_openref_t *added)
-{
- while (!h2o_linklist_is_empty(&parent->_all_refs)) {
- h2o_http2_scheduler_openref_t *child_ref =
- H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_openref_t, _all_link, parent->_all_refs.next);
- if (child_ref == added) {
- /* precond: the added node should exist as the last item within parent */
- assert(parent->_all_refs.prev == &added->_all_link);
- break;
- }
- h2o_http2_scheduler_rebind(child_ref, &added->node, h2o_http2_scheduler_get_weight(child_ref), 0);
- }
-}
-
-void h2o_http2_scheduler_open(h2o_http2_scheduler_openref_t *ref, h2o_http2_scheduler_node_t *parent, uint16_t weight,
- int exclusive)
-{
- init_node(&ref->node, parent);
- ref->weight = weight;
- ref->_all_link = (h2o_linklist_t){NULL};
- ref->_active_cnt = 0;
- ref->_self_is_active = 0;
- ref->_queue_node = (h2o_http2_scheduler_queue_node_t){{NULL}};
-
- h2o_linklist_insert(&parent->_all_refs, &ref->_all_link);
-
- if (exclusive)
- convert_to_exclusive(parent, ref);
-}
-
-void h2o_http2_scheduler_close(h2o_http2_scheduler_openref_t *ref)
-{
- assert(h2o_http2_scheduler_is_open(ref));
-
- /* move dependents to parent */
- if (!h2o_linklist_is_empty(&ref->node._all_refs)) {
- /* proportionally distribute the weight to the children (draft-16 5.3.4) */
- uint32_t total_weight = 0, factor;
- h2o_linklist_t *link;
- for (link = ref->node._all_refs.next; link != &ref->node._all_refs; link = link->next) {
- h2o_http2_scheduler_openref_t *child_ref = H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_openref_t, _all_link, link);
- total_weight += child_ref->weight;
- }
- assert(total_weight != 0);
- factor = ((uint32_t)ref->weight * 65536 + total_weight / 2) / total_weight;
- do {
- h2o_http2_scheduler_openref_t *child_ref =
- H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_openref_t, _all_link, ref->node._all_refs.next);
- uint16_t weight = (child_ref->weight * factor / 32768 + 1) / 2;
- if (weight < 1)
- weight = 1;
- else if (weight > 256)
- weight = 256;
- h2o_http2_scheduler_rebind(child_ref, ref->node._parent, weight, 0);
- } while (!h2o_linklist_is_empty(&ref->node._all_refs));
- }
-
- free(ref->node._queue);
- ref->node._queue = NULL;
-
- /* detach self */
- h2o_linklist_unlink(&ref->_all_link);
- if (ref->_self_is_active) {
- assert(ref->_active_cnt == 1);
- queue_unset(&ref->_queue_node);
- decr_active_cnt(ref->node._parent);
- } else {
- assert(ref->_active_cnt == 0);
- }
-}
-
-static void do_rebind(h2o_http2_scheduler_openref_t *ref, h2o_http2_scheduler_node_t *new_parent, int exclusive)
-{
- /* rebind _all_link */
- h2o_linklist_unlink(&ref->_all_link);
- h2o_linklist_insert(&new_parent->_all_refs, &ref->_all_link);
- /* rebind to WRR (as well as adjust active_cnt) */
- if (ref->_active_cnt != 0) {
- queue_unset(&ref->_queue_node);
- queue_set(get_queue(new_parent), &ref->_queue_node, ref->weight);
- decr_active_cnt(ref->node._parent);
- incr_active_cnt(new_parent);
- }
- /* update the backlinks */
- ref->node._parent = new_parent;
-
- if (exclusive)
- convert_to_exclusive(new_parent, ref);
-}
-
-void h2o_http2_scheduler_rebind(h2o_http2_scheduler_openref_t *ref, h2o_http2_scheduler_node_t *new_parent, uint16_t weight,
- int exclusive)
-{
- assert(h2o_http2_scheduler_is_open(ref));
- assert(&ref->node != new_parent);
- assert(1 <= weight);
- assert(weight <= 257);
-
- /* do nothing if there'd be no change at all */
- if (ref->node._parent == new_parent && ref->weight == weight && !exclusive)
- return;
-
- ref->weight = weight;
-
- { /* if new_parent is dependent to ref, make new_parent a sibling of ref before applying the final transition (see draft-16
- 5.3.3) */
- h2o_http2_scheduler_node_t *t;
- for (t = new_parent; t->_parent != NULL; t = t->_parent) {
- if (t->_parent == &ref->node) {
- /* quoting the spec: "The moved dependency retains its weight." */
- h2o_http2_scheduler_openref_t *new_parent_ref = (void *)new_parent;
- do_rebind(new_parent_ref, ref->node._parent, 0);
- break;
- }
- }
- }
-
- do_rebind(ref, new_parent, exclusive);
-}
-
-void h2o_http2_scheduler_init(h2o_http2_scheduler_node_t *root)
-{
- init_node(root, NULL);
-}
-
-void h2o_http2_scheduler_dispose(h2o_http2_scheduler_node_t *root)
-{
- free(root->_queue);
- root->_queue = NULL;
-}
-
-void h2o_http2_scheduler_activate(h2o_http2_scheduler_openref_t *ref)
-{
- if (ref->_self_is_active)
- return;
- ref->_self_is_active = 1;
- incr_active_cnt(&ref->node);
-}
-
-static int proceed(h2o_http2_scheduler_node_t *node, h2o_http2_scheduler_run_cb cb, void *cb_arg)
-{
-Redo:
- if (node->_queue == NULL)
- return 0;
-
- h2o_http2_scheduler_queue_node_t *drr_node = queue_pop(node->_queue);
- if (drr_node == NULL)
- return 0;
-
- h2o_http2_scheduler_openref_t *ref = H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_openref_t, _queue_node, drr_node);
-
- if (!ref->_self_is_active) {
- /* run the children (manually-unrolled tail recursion) */
- queue_set(node->_queue, &ref->_queue_node, ref->weight);
- node = &ref->node;
- goto Redo;
- }
- assert(ref->_active_cnt != 0);
-
- /* call the callbacks */
- int still_is_active, bail_out = cb(ref, &still_is_active, cb_arg);
- if (still_is_active) {
- queue_set(node->_queue, &ref->_queue_node, ref->weight);
- } else {
- ref->_self_is_active = 0;
- if (--ref->_active_cnt != 0) {
- queue_set(node->_queue, &ref->_queue_node, ref->weight);
- } else if (ref->node._parent != NULL) {
- decr_active_cnt(ref->node._parent);
- }
- }
-
- return bail_out;
-}
-
-int h2o_http2_scheduler_run(h2o_http2_scheduler_node_t *root, h2o_http2_scheduler_run_cb cb, void *cb_arg)
-{
- if (root->_queue != NULL) {
- while (!queue_is_empty(root->_queue)) {
- int bail_out = proceed(root, cb, cb_arg);
- if (bail_out)
- return bail_out;
- }
- }
- return 0;
-}
-
-int h2o_http2_scheduler_is_active(h2o_http2_scheduler_node_t *root)
-{
- return root->_queue != NULL && !queue_is_empty(root->_queue);
-}
diff --git a/web/server/h2o/libh2o/lib/http2/stream.c b/web/server/h2o/libh2o/lib/http2/stream.c
deleted file mode 100644
index 1dfe2c3a3..000000000
--- a/web/server/h2o/libh2o/lib/http2/stream.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * 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 "h2o.h"
-#include "h2o/http2.h"
-#include "h2o/http2_internal.h"
-
-static void finalostream_start_pull(h2o_ostream_t *self, h2o_ostream_pull_cb cb);
-static void finalostream_send(h2o_ostream_t *self, h2o_req_t *req, h2o_iovec_t *bufs, size_t bufcnt, h2o_send_state_t state);
-
-static size_t sz_min(size_t x, size_t y)
-{
- return x < y ? x : y;
-}
-
-h2o_http2_stream_t *h2o_http2_stream_open(h2o_http2_conn_t *conn, uint32_t stream_id, h2o_req_t *src_req,
- const h2o_http2_priority_t *received_priority)
-{
- h2o_http2_stream_t *stream = h2o_mem_alloc(sizeof(*stream));
-
- /* init properties (other than req) */
- memset(stream, 0, offsetof(h2o_http2_stream_t, req));
- stream->stream_id = stream_id;
- stream->_ostr_final.do_send = finalostream_send;
- stream->_ostr_final.start_pull = finalostream_start_pull;
- stream->state = H2O_HTTP2_STREAM_STATE_IDLE;
- h2o_http2_window_init(&stream->output_window, &conn->peer_settings);
- h2o_http2_window_init(&stream->input_window, &H2O_HTTP2_SETTINGS_HOST);
- stream->received_priority = *received_priority;
- stream->_expected_content_length = SIZE_MAX;
-
- /* init request */
- h2o_init_request(&stream->req, &conn->super, src_req);
- stream->req.version = 0x200;
- if (src_req != NULL)
- memset(&stream->req.upgrade, 0, sizeof(stream->req.upgrade));
- stream->req._ostr_top = &stream->_ostr_final;
-
- h2o_http2_conn_register_stream(conn, stream);
-
- ++conn->num_streams.priority.open;
- stream->_num_streams_slot = &conn->num_streams.priority;
-
- return stream;
-}
-
-void h2o_http2_stream_close(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- h2o_http2_conn_unregister_stream(conn, stream);
- if (stream->_req_body != NULL)
- h2o_buffer_dispose(&stream->_req_body);
- if (stream->cache_digests != NULL)
- h2o_cache_digests_destroy(stream->cache_digests);
- h2o_dispose_request(&stream->req);
- if (stream->stream_id == 1 && conn->_http1_req_input != NULL)
- h2o_buffer_dispose(&conn->_http1_req_input);
- free(stream);
-}
-
-void h2o_http2_stream_reset(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- switch (stream->state) {
- case H2O_HTTP2_STREAM_STATE_IDLE:
- case H2O_HTTP2_STREAM_STATE_RECV_HEADERS:
- case H2O_HTTP2_STREAM_STATE_RECV_BODY:
- case H2O_HTTP2_STREAM_STATE_REQ_PENDING:
- h2o_http2_stream_close(conn, stream);
- break;
- case H2O_HTTP2_STREAM_STATE_SEND_HEADERS:
- case H2O_HTTP2_STREAM_STATE_SEND_BODY:
- case H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL:
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_END_STREAM);
- /* continues */
- case H2O_HTTP2_STREAM_STATE_END_STREAM:
- /* clear all the queued bufs, and close the connection in the callback */
- stream->_data.size = 0;
- if (h2o_linklist_is_linked(&stream->_refs.link)) {
- /* will be closed in the callback */
- } else {
- h2o_http2_stream_close(conn, stream);
- }
- break;
- }
-}
-
-static size_t calc_max_payload_size(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- ssize_t conn_max, stream_max;
-
- if ((conn_max = h2o_http2_conn_get_buffer_window(conn)) <= 0)
- return 0;
- if ((stream_max = h2o_http2_window_get_window(&stream->output_window)) <= 0)
- return 0;
- return sz_min(sz_min(conn_max, stream_max), conn->peer_settings.max_frame_size);
-}
-
-static void commit_data_header(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, h2o_buffer_t **outbuf, size_t length,
- h2o_send_state_t send_state)
-{
- assert(outbuf != NULL);
- /* send a DATA frame if there's data or the END_STREAM flag to send */
- if (length || send_state == H2O_SEND_STATE_FINAL) {
- h2o_http2_encode_frame_header((void *)((*outbuf)->bytes + (*outbuf)->size), length, H2O_HTTP2_FRAME_TYPE_DATA,
- send_state == H2O_SEND_STATE_FINAL ? H2O_HTTP2_FRAME_FLAG_END_STREAM : 0, stream->stream_id);
- h2o_http2_window_consume_window(&conn->_write.window, length);
- h2o_http2_window_consume_window(&stream->output_window, length);
- (*outbuf)->size += length + H2O_HTTP2_FRAME_HEADER_SIZE;
- stream->req.bytes_sent += length;
- }
- /* send a RST_STREAM if there's an error */
- if (send_state == H2O_SEND_STATE_ERROR) {
- h2o_http2_encode_rst_stream_frame(outbuf, stream->stream_id, -H2O_HTTP2_ERROR_PROTOCOL);
- }
-}
-
-static h2o_send_state_t send_data_pull(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- size_t max_payload_size;
- h2o_iovec_t cbuf;
- h2o_send_state_t send_state = H2O_SEND_STATE_IN_PROGRESS;
-
- if ((max_payload_size = calc_max_payload_size(conn, stream)) == 0)
- goto Exit;
- /* reserve buffer */
- h2o_buffer_reserve(&conn->_write.buf, H2O_HTTP2_FRAME_HEADER_SIZE + max_payload_size);
- /* obtain content */
- cbuf.base = conn->_write.buf->bytes + conn->_write.buf->size + H2O_HTTP2_FRAME_HEADER_SIZE;
- cbuf.len = max_payload_size;
- send_state = h2o_pull(&stream->req, stream->_pull_cb, &cbuf);
- /* write the header */
- commit_data_header(conn, stream, &conn->_write.buf, cbuf.len, send_state);
-
-Exit:
- return send_state;
-}
-
-static h2o_iovec_t *send_data_push(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, h2o_iovec_t *bufs, size_t bufcnt,
- h2o_send_state_t send_state)
-{
- h2o_iovec_t dst;
- size_t max_payload_size;
-
- if ((max_payload_size = calc_max_payload_size(conn, stream)) == 0)
- goto Exit;
-
- /* reserve buffer and point dst to the payload */
- dst.base =
- h2o_buffer_reserve(&conn->_write.buf, H2O_HTTP2_FRAME_HEADER_SIZE + max_payload_size).base + H2O_HTTP2_FRAME_HEADER_SIZE;
- dst.len = max_payload_size;
-
- /* emit data */
- while (bufcnt != 0) {
- if (bufs->len != 0)
- break;
- ++bufs;
- --bufcnt;
- }
- while (bufcnt != 0) {
- size_t fill_size = sz_min(dst.len, bufs->len);
- memcpy(dst.base, bufs->base, fill_size);
- dst.base += fill_size;
- dst.len -= fill_size;
- bufs->base += fill_size;
- bufs->len -= fill_size;
- while (bufs->len == 0) {
- ++bufs;
- --bufcnt;
- if (bufcnt == 0)
- break;
- }
- if (dst.len == 0)
- break;
- }
-
- /* commit the DATA frame if we have actually emitted payload */
- if (dst.len != max_payload_size || !h2o_send_state_is_in_progress(send_state)) {
- size_t payload_len = max_payload_size - dst.len;
- if (bufcnt != 0) {
- send_state = H2O_SEND_STATE_IN_PROGRESS;
- }
- commit_data_header(conn, stream, &conn->_write.buf, payload_len, send_state);
- }
-
-Exit:
- return bufs;
-}
-
-static int is_blocking_asset(h2o_req_t *req)
-{
- if (req->res.mime_attr == NULL)
- h2o_req_fill_mime_attributes(req);
- return req->res.mime_attr->priority == H2O_MIME_ATTRIBUTE_PRIORITY_HIGHEST;
-}
-
-static int send_headers(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- h2o_timestamp_t ts;
-
- h2o_get_timestamp(conn->super.ctx, &stream->req.pool, &ts);
-
- /* cancel push with an error response */
- if (h2o_http2_stream_is_push(stream->stream_id)) {
- if (400 <= stream->req.res.status)
- goto CancelPush;
- if (stream->cache_digests != NULL) {
- ssize_t etag_index = h2o_find_header(&stream->req.headers, H2O_TOKEN_ETAG, -1);
- if (etag_index != -1) {
- h2o_iovec_t url = h2o_concat(&stream->req.pool, stream->req.input.scheme->name, h2o_iovec_init(H2O_STRLIT("://")),
- stream->req.input.authority, stream->req.input.path);
- h2o_iovec_t *etag = &stream->req.headers.entries[etag_index].value;
- if (h2o_cache_digests_lookup_by_url_and_etag(stream->cache_digests, url.base, url.len, etag->base, etag->len) ==
- H2O_CACHE_DIGESTS_STATE_FRESH)
- goto CancelPush;
- }
- }
- }
-
- /* reset casper cookie in case cache-digests exist */
- if (stream->cache_digests != NULL && stream->req.hostconf->http2.casper.capacity_bits != 0) {
- h2o_add_header(&stream->req.pool, &stream->req.res.headers, H2O_TOKEN_SET_COOKIE, NULL,
- H2O_STRLIT("h2o_casper=; Path=/; Expires=Sat, 01 Jan 2000 00:00:00 GMT"));
- }
-
- /* CASPER */
- if (conn->casper != NULL) {
- /* update casper if necessary */
- if (stream->req.hostconf->http2.casper.track_all_types || is_blocking_asset(&stream->req)) {
- if (h2o_http2_casper_lookup(conn->casper, stream->req.path.base, stream->req.path.len, 1)) {
- /* cancel if the pushed resource is already marked as cached */
- if (h2o_http2_stream_is_push(stream->stream_id))
- goto CancelPush;
- }
- }
- if (stream->cache_digests != NULL)
- goto SkipCookie;
- /* browsers might ignore push responses, or they may process the responses in a different order than they were pushed.
- * Therefore H2O tries to include casper cookie only in the last stream that may be received by the client, or when the
- * value become stable; see also: https://github.com/h2o/h2o/issues/421
- */
- if (h2o_http2_stream_is_push(stream->stream_id)) {
- if (!(conn->num_streams.pull.open == 0 && (conn->num_streams.push.half_closed - conn->num_streams.push.send_body) == 1))
- goto SkipCookie;
- } else {
- if (conn->num_streams.push.half_closed - conn->num_streams.push.send_body != 0)
- goto SkipCookie;
- }
- h2o_iovec_t cookie = h2o_http2_casper_get_cookie(conn->casper);
- h2o_add_header(&stream->req.pool, &stream->req.res.headers, H2O_TOKEN_SET_COOKIE, NULL, cookie.base, cookie.len);
- SkipCookie:;
- }
-
- if (h2o_http2_stream_is_push(stream->stream_id)) {
- /* for push, send the push promise */
- if (!stream->push.promise_sent)
- h2o_http2_stream_send_push_promise(conn, stream);
- /* send ASAP if it is a blocking asset (even in case of Firefox we can't wait 1RTT for it to reprioritize the asset) */
- if (is_blocking_asset(&stream->req))
- h2o_http2_scheduler_rebind(&stream->_refs.scheduler, &conn->scheduler, 257, 0);
- } else {
- /* raise the priority of asset files that block rendering to highest if the user-agent is _not_ using dependency-based
- * prioritization (e.g. that of Firefox)
- */
- if (conn->num_streams.priority.open == 0 && stream->req.hostconf->http2.reprioritize_blocking_assets &&
- h2o_http2_scheduler_get_parent(&stream->_refs.scheduler) == &conn->scheduler && is_blocking_asset(&stream->req))
- h2o_http2_scheduler_rebind(&stream->_refs.scheduler, &conn->scheduler, 257, 0);
- }
-
- /* send HEADERS, as well as start sending body */
- if (h2o_http2_stream_is_push(stream->stream_id))
- h2o_add_header_by_str(&stream->req.pool, &stream->req.res.headers, H2O_STRLIT("x-http2-push"), 0, NULL,
- H2O_STRLIT("pushed"));
- h2o_hpack_flatten_response(&conn->_write.buf, &conn->_output_header_table, stream->stream_id,
- conn->peer_settings.max_frame_size, &stream->req.res, &ts, &conn->super.ctx->globalconf->server_name,
- stream->req.res.content_length);
- h2o_http2_conn_request_write(conn);
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_BODY);
-
- return 0;
-
-CancelPush:
- h2o_add_header_by_str(&stream->req.pool, &stream->req.res.headers, H2O_STRLIT("x-http2-push"), 0, NULL,
- H2O_STRLIT("cancelled"));
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_END_STREAM);
- h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_refs.link);
- if (stream->push.promise_sent) {
- h2o_http2_encode_rst_stream_frame(&conn->_write.buf, stream->stream_id, -H2O_HTTP2_ERROR_INTERNAL);
- h2o_http2_conn_request_write(conn);
- }
- return -1;
-}
-
-void finalostream_start_pull(h2o_ostream_t *self, h2o_ostream_pull_cb cb)
-{
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _ostr_final, self);
- h2o_http2_conn_t *conn = (void *)stream->req.conn;
-
- assert(stream->req._ostr_top == &stream->_ostr_final);
- assert(stream->state == H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
-
- /* register the pull callback */
- stream->_pull_cb = cb;
-
- /* send headers */
- if (send_headers(conn, stream) != 0)
- return;
-
- /* set dummy data in the send buffer */
- h2o_vector_reserve(&stream->req.pool, &stream->_data, 1);
- stream->_data.entries[0].base = "<pull interface>";
- stream->_data.entries[0].len = 1;
- stream->_data.size = 1;
-
- h2o_http2_conn_register_for_proceed_callback(conn, stream);
-}
-
-void finalostream_send(h2o_ostream_t *self, h2o_req_t *req, h2o_iovec_t *bufs, size_t bufcnt, h2o_send_state_t state)
-{
- h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _ostr_final, self);
- h2o_http2_conn_t *conn = (h2o_http2_conn_t *)req->conn;
-
- assert(stream->_data.size == 0);
-
- stream->send_state = state;
-
- /* send headers */
- switch (stream->state) {
- case H2O_HTTP2_STREAM_STATE_SEND_HEADERS:
- if (send_headers(conn, stream) != 0)
- return;
- /* fallthru */
- case H2O_HTTP2_STREAM_STATE_SEND_BODY:
- if (state != H2O_SEND_STATE_IN_PROGRESS) {
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL);
- }
- break;
- case H2O_HTTP2_STREAM_STATE_END_STREAM:
- /* might get set by h2o_http2_stream_reset */
- return;
- default:
- assert(!"cannot be in a receiving state");
- }
-
- /* save the contents in queue */
- if (bufcnt != 0) {
- h2o_vector_reserve(&req->pool, &stream->_data, bufcnt);
- memcpy(stream->_data.entries, bufs, sizeof(h2o_iovec_t) * bufcnt);
- stream->_data.size = bufcnt;
- }
-
- h2o_http2_conn_register_for_proceed_callback(conn, stream);
-}
-
-void h2o_http2_stream_send_pending_data(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- if (h2o_http2_window_get_window(&stream->output_window) <= 0)
- return;
-
- if (stream->_pull_cb != NULL) {
- h2o_send_state_t send_state;
- /* pull mode */
- assert(stream->state != H2O_HTTP2_STREAM_STATE_END_STREAM);
- send_state = send_data_pull(conn, stream);
- if (send_state != H2O_SEND_STATE_IN_PROGRESS) {
- /* sent all data */
- stream->_data.size = 0;
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_END_STREAM);
- }
- } else {
- /* push mode */
- h2o_iovec_t *nextbuf = send_data_push(conn, stream, stream->_data.entries, stream->_data.size, stream->send_state);
- if (nextbuf == stream->_data.entries + stream->_data.size) {
- /* sent all data */
- stream->_data.size = 0;
- if (stream->state == H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL)
- h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_END_STREAM);
- } else if (nextbuf != stream->_data.entries) {
- /* adjust the buffer */
- size_t newsize = stream->_data.size - (nextbuf - stream->_data.entries);
- memmove(stream->_data.entries, nextbuf, sizeof(h2o_iovec_t) * newsize);
- stream->_data.size = newsize;
- }
- }
-}
-
-void h2o_http2_stream_proceed(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
-{
- if (stream->state == H2O_HTTP2_STREAM_STATE_END_STREAM) {
- h2o_http2_stream_close(conn, stream);
- } else {
- h2o_proceed_response(&stream->req);
- }
-}
diff --git a/web/server/h2o/libh2o/lib/tunnel.c b/web/server/h2o/libh2o/lib/tunnel.c
deleted file mode 100644
index aa86aaf4d..000000000
--- a/web/server/h2o/libh2o/lib/tunnel.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2015 Justin Zhu, DeNA Co., Ltd., Kazuho Oku
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include "h2o.h"
-#include "h2o/http1.h"
-#include "h2o/tunnel.h"
-
-struct st_h2o_tunnel_t {
- h2o_context_t *ctx;
- h2o_timeout_entry_t timeout_entry;
- h2o_timeout_t *timeout;
- h2o_socket_t *sock[2];
-};
-
-static void on_write_complete(h2o_socket_t *sock, const char *err);
-
-static void close_connection(struct st_h2o_tunnel_t *tunnel)
-{
- h2o_timeout_unlink(&tunnel->timeout_entry);
-
- h2o_socket_close(tunnel->sock[0]);
- h2o_socket_close(tunnel->sock[1]);
-
- free(tunnel);
-}
-
-static void on_timeout(h2o_timeout_entry_t *entry)
-{
- struct st_h2o_tunnel_t *tunnel = H2O_STRUCT_FROM_MEMBER(struct st_h2o_tunnel_t, timeout_entry, entry);
- close_connection(tunnel);
-}
-
-static inline void reset_timeout(struct st_h2o_tunnel_t *tunnel)
-{
- h2o_timeout_unlink(&tunnel->timeout_entry);
- h2o_timeout_link(tunnel->ctx->loop, tunnel->timeout, &tunnel->timeout_entry);
-}
-
-static inline void on_read(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_tunnel_t *tunnel = sock->data;
- h2o_socket_t *dst;
- assert(tunnel != NULL);
- assert(tunnel->sock[0] == sock || tunnel->sock[1] == sock);
-
- if (err != NULL) {
- close_connection(tunnel);
- return;
- }
-
- if (sock->bytes_read == 0)
- return;
-
- h2o_socket_read_stop(sock);
- reset_timeout(tunnel);
-
- if (tunnel->sock[0] == sock)
- dst = tunnel->sock[1];
- else
- dst = tunnel->sock[0];
-
- h2o_iovec_t buf;
- buf.base = sock->input->bytes;
- buf.len = sock->input->size;
- h2o_socket_write(dst, &buf, 1, on_write_complete);
-}
-
-static void on_write_complete(h2o_socket_t *sock, const char *err)
-{
- struct st_h2o_tunnel_t *tunnel = sock->data;
- h2o_socket_t *peer;
- assert(tunnel != NULL);
- assert(tunnel->sock[0] == sock || tunnel->sock[1] == sock);
-
- if (err != NULL) {
- close_connection(tunnel);
- return;
- }
-
- reset_timeout(tunnel);
-
- if (tunnel->sock[0] == sock)
- peer = tunnel->sock[1];
- else
- peer = tunnel->sock[0];
-
- h2o_buffer_consume(&peer->input, peer->input->size);
- h2o_socket_read_start(peer, on_read);
-}
-
-h2o_tunnel_t *h2o_tunnel_establish(h2o_context_t *ctx, h2o_socket_t *sock1, h2o_socket_t *sock2, h2o_timeout_t *timeout)
-{
- h2o_tunnel_t *tunnel = h2o_mem_alloc(sizeof(*tunnel));
- tunnel->ctx = ctx;
- tunnel->timeout = timeout;
- tunnel->timeout_entry = (h2o_timeout_entry_t){0};
- tunnel->timeout_entry.cb = on_timeout;
- tunnel->sock[0] = sock1;
- tunnel->sock[1] = sock2;
- sock1->data = tunnel;
- sock2->data = tunnel;
- h2o_timeout_link(tunnel->ctx->loop, tunnel->timeout, &tunnel->timeout_entry);
-
- /* Bring up the tunnel. Note. Upstream always ready first. */
- if (sock2->input->size)
- on_read(sock2, NULL);
- if (sock1->input->size)
- on_read(sock1, NULL);
- h2o_socket_read_start(sock2, on_read);
- h2o_socket_read_start(sock1, on_read);
-
- return tunnel;
-}
-
-void h2o_tunnel_break(h2o_tunnel_t *tunnel)
-{
- close_connection(tunnel);
-}
diff --git a/web/server/h2o/libh2o/lib/websocket.c b/web/server/h2o/libh2o/lib/websocket.c
deleted file mode 100644
index 2886acda6..000000000
--- a/web/server/h2o/libh2o/lib/websocket.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * 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 <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <openssl/sha.h>
-#include "h2o/websocket.h"
-
-#define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
-
-static void create_accept_key(char *dst, const char *client_key)
-{
- uint8_t sha1buf[20], key_src[60];
-
- memcpy(key_src, client_key, 24);
- memcpy(key_src + 24, WS_GUID, 36);
- SHA1(key_src, sizeof(key_src), sha1buf);
- h2o_base64_encode(dst, sha1buf, sizeof(sha1buf), 0);
- dst[28] = '\0';
-}
-
-static void on_close(h2o_websocket_conn_t *conn)
-{
- (*conn->cb)(conn, NULL);
-}
-
-static void on_recv(h2o_socket_t *sock, const char *err)
-{
- h2o_websocket_conn_t *conn = sock->data;
-
- if (err != NULL) {
- on_close(conn);
- return;
- }
- h2o_websocket_proceed(conn);
-}
-
-static void on_write_complete(h2o_socket_t *sock, const char *err)
-{
- h2o_websocket_conn_t *conn = sock->data;
-
- if (err != NULL) {
- on_close(conn);
- return;
- }
- h2o_websocket_proceed(conn);
-}
-
-static ssize_t recv_callback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, int flags, void *_conn)
-{
- h2o_websocket_conn_t *conn = _conn;
-
- /* return WOULDBLOCK if no data */
- if (conn->sock->input->size == 0) {
- wslay_event_set_error(conn->ws_ctx, WSLAY_ERR_WOULDBLOCK);
- return -1;
- }
-
- if (conn->sock->input->size < len)
- len = conn->sock->input->size;
- memcpy(buf, conn->sock->input->bytes, len);
- h2o_buffer_consume(&conn->sock->input, len);
- return len;
-}
-
-static ssize_t send_callback(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *_conn)
-{
- h2o_websocket_conn_t *conn = _conn;
- h2o_iovec_t buf;
-
- /* return WOULDBLOCK if pending (TODO: queue fixed number of chunks, instead of only one) */
- if (h2o_socket_is_writing(conn->sock)) {
- wslay_event_set_error(conn->ws_ctx, WSLAY_ERR_WOULDBLOCK);
- return -1;
- }
-
- /* copy data */
- conn->_write_buf = h2o_mem_realloc(conn->_write_buf, len);
- memcpy(conn->_write_buf, data, len);
-
- /* write */
- buf.base = conn->_write_buf;
- buf.len = len;
- h2o_socket_write(conn->sock, &buf, 1, on_write_complete);
-
- return len;
-}
-
-static void on_msg_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, void *_conn)
-{
- h2o_websocket_conn_t *conn = _conn;
- (*conn->cb)(conn, arg);
-}
-
-static void on_complete(void *user_data, h2o_socket_t *sock, size_t reqsize)
-{
- h2o_websocket_conn_t *conn = user_data;
-
- /* close the connection on error */
- if (sock == NULL) {
- (*conn->cb)(conn, NULL);
- return;
- }
-
- conn->sock = sock;
- sock->data = conn;
- h2o_buffer_consume(&sock->input, reqsize);
- h2o_websocket_proceed(conn);
-}
-
-h2o_websocket_conn_t *h2o_upgrade_to_websocket(h2o_req_t *req, const char *client_key, void *data, h2o_websocket_msg_callback cb)
-{
- h2o_websocket_conn_t *conn = h2o_mem_alloc(sizeof(*conn));
- char accept_key[29];
-
- /* only for http1 connection */
- assert(req->version < 0x200);
-
- /* setup the context */
- memset(conn, 0, sizeof(*conn));
- // conn->sock = sock; set by on_complete
- conn->ws_callbacks.recv_callback = recv_callback;
- conn->ws_callbacks.send_callback = send_callback;
- conn->ws_callbacks.on_msg_recv_callback = on_msg_callback;
- conn->data = data;
- conn->cb = cb;
-
- wslay_event_context_server_init(&conn->ws_ctx, &conn->ws_callbacks, conn);
-
- /* build response */
- create_accept_key(accept_key, client_key);
- req->res.status = 101;
- req->res.reason = "Switching Protocols";
- h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_UPGRADE, NULL, H2O_STRLIT("websocket"));
- h2o_add_header_by_str(&req->pool, &req->res.headers, H2O_STRLIT("sec-websocket-accept"), 0, NULL, accept_key,
- strlen(accept_key));
-
- /* send */
- h2o_http1_upgrade(req, NULL, 0, on_complete, conn);
-
- return conn;
-}
-
-int h2o_is_websocket_handshake(h2o_req_t *req, const char **ws_client_key)
-{
- ssize_t key_header_index;
-
- *ws_client_key = NULL;
-
- /* method */
- if (h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("GET"))) {
- /* ok */
- } else {
- return 0;
- }
-
- /* upgrade header */
- if (req->upgrade.base != NULL && h2o_lcstris(req->upgrade.base, req->upgrade.len, H2O_STRLIT("websocket"))) {
- /* ok */
- } else {
- return 0;
- }
- /* sec-websocket-key header */
- if ((key_header_index = h2o_find_header_by_str(&req->headers, H2O_STRLIT("sec-websocket-key"), -1)) != -1) {
- if (req->headers.entries[key_header_index].value.len != 24) {
- return -1;
- }
- } else {
- return 0;
- }
-
- *ws_client_key = req->headers.entries[key_header_index].value.base;
- return 0;
-}
-
-void h2o_websocket_close(h2o_websocket_conn_t *conn)
-{
- if (conn->sock != NULL)
- h2o_socket_close(conn->sock);
- free(conn->_write_buf);
- wslay_event_context_free(conn->ws_ctx);
- free(conn);
-}
-
-void h2o_websocket_proceed(h2o_websocket_conn_t *conn)
-{
- int handled;
-
- /* run the loop until getting to a point where no more progress can be achieved */
- do {
- handled = 0;
- if (!h2o_socket_is_writing(conn->sock) && wslay_event_want_write(conn->ws_ctx)) {
- if (wslay_event_send(conn->ws_ctx) != 0) {
- goto Close;
- }
- handled = 1;
- }
- if (conn->sock->input->size != 0 && wslay_event_want_read(conn->ws_ctx)) {
- if (wslay_event_recv(conn->ws_ctx) != 0) {
- goto Close;
- }
- handled = 1;
- }
- } while (handled);
-
- if (wslay_event_want_read(conn->ws_ctx)) {
- h2o_socket_read_start(conn->sock, on_recv);
- } else if (h2o_socket_is_writing(conn->sock) || wslay_event_want_write(conn->ws_ctx)) {
- h2o_socket_read_stop(conn->sock);
- } else {
- /* nothing is going on... close the socket */
- goto Close;
- }
-
- return;
-
-Close:
- on_close(conn);
-}