From ca55d1b822cd1fa992180c32f4fe9de1fc1a6d56 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 5 Feb 2014 23:22:31 +0900 Subject: [PATCH] Update doc --- _sources/apiref.txt | 7 +- _sources/index.txt | 1 + _static/css/badge_only.css | 2 +- _static/css/theme.css | 2 +- apiref.html | 16 +- genindex.html | 6 +- index.html | 9 +- nghttp2.h.html | 19 +- nghttp2ver.h.html | 12 +- objects.inv | Bin 2113 -> 2129 bytes package_README.html | 12 +- released-versions/v0.3.0/.buildinfo | 4 + released-versions/v0.3.0/_sources/apiref.txt | 2047 ++++ released-versions/v0.3.0/_sources/index.txt | 39 + .../v0.3.0/_sources/nghttp2.h.txt | 4 + .../v0.3.0/_sources/nghttp2ver.h.txt | 4 + .../v0.3.0/_sources/package_README.txt | 1 + .../v0.3.0/_sources/tutorial-client.txt | 489 + .../v0.3.0/_sources/tutorial-server.txt | 595 ++ .../v0.3.0/_static/ajax-loader.gif | Bin 0 -> 673 bytes released-versions/v0.3.0/_static/basic.css | 540 + .../v0.3.0/_static/comment-bright.png | Bin 0 -> 3500 bytes .../v0.3.0/_static/comment-close.png | Bin 0 -> 3578 bytes released-versions/v0.3.0/_static/comment.png | Bin 0 -> 3445 bytes .../v0.3.0/_static/css/badge_only.css | 1 + .../v0.3.0/_static/css/theme.css | 4 + released-versions/v0.3.0/_static/doctools.js | 247 + .../v0.3.0/_static/down-pressed.png | Bin 0 -> 368 bytes released-versions/v0.3.0/_static/down.png | Bin 0 -> 363 bytes released-versions/v0.3.0/_static/file.png | Bin 0 -> 392 bytes .../_static/font/fontawesome_webfont.eot | Bin 0 -> 37405 bytes .../_static/font/fontawesome_webfont.svg | 399 + .../_static/font/fontawesome_webfont.ttf | Bin 0 -> 79076 bytes .../_static/font/fontawesome_webfont.woff | Bin 0 -> 43572 bytes .../v0.3.0/_static/fonts/FontAwesome.otf | Bin 0 -> 62856 bytes .../_static/fonts/fontawesome-webfont.eot | Bin 0 -> 38205 bytes .../_static/fonts/fontawesome-webfont.svg | 414 + .../_static/fonts/fontawesome-webfont.ttf | Bin 0 -> 80652 bytes .../_static/fonts/fontawesome-webfont.woff | Bin 0 -> 44432 bytes released-versions/v0.3.0/_static/jquery.js | 9404 +++++++++++++++++ released-versions/v0.3.0/_static/js/theme.js | 47 + released-versions/v0.3.0/_static/minus.png | Bin 0 -> 199 bytes released-versions/v0.3.0/_static/plus.png | Bin 0 -> 199 bytes released-versions/v0.3.0/_static/pygments.css | 62 + .../v0.3.0/_static/searchtools.js | 560 + .../v0.3.0/_static/underscore.js | 1226 +++ .../v0.3.0/_static/up-pressed.png | Bin 0 -> 372 bytes released-versions/v0.3.0/_static/up.png | Bin 0 -> 363 bytes .../v0.3.0/_static/websupport.js | 808 ++ released-versions/v0.3.0/apiref.html | 2619 +++++ released-versions/v0.3.0/genindex.html | 1125 ++ released-versions/v0.3.0/index.html | 239 + released-versions/v0.3.0/nghttp2.h.html | 2548 +++++ released-versions/v0.3.0/nghttp2ver.h.html | 229 + released-versions/v0.3.0/objects.inv | Bin 0 -> 2128 bytes released-versions/v0.3.0/package_README.html | 1083 ++ released-versions/v0.3.0/search.html | 191 + released-versions/v0.3.0/searchindex.js | 1 + released-versions/v0.3.0/tutorial-client.html | 1237 +++ released-versions/v0.3.0/tutorial-server.html | 1500 +++ search.html | 6 +- searchindex.js | 2 +- tutorial-client.html | 10 +- tutorial-server.html | 10 +- 64 files changed, 27729 insertions(+), 52 deletions(-) create mode 100644 released-versions/v0.3.0/.buildinfo create mode 100644 released-versions/v0.3.0/_sources/apiref.txt create mode 100644 released-versions/v0.3.0/_sources/index.txt create mode 100644 released-versions/v0.3.0/_sources/nghttp2.h.txt create mode 100644 released-versions/v0.3.0/_sources/nghttp2ver.h.txt create mode 100644 released-versions/v0.3.0/_sources/package_README.txt create mode 100644 released-versions/v0.3.0/_sources/tutorial-client.txt create mode 100644 released-versions/v0.3.0/_sources/tutorial-server.txt create mode 100644 released-versions/v0.3.0/_static/ajax-loader.gif create mode 100644 released-versions/v0.3.0/_static/basic.css create mode 100644 released-versions/v0.3.0/_static/comment-bright.png create mode 100644 released-versions/v0.3.0/_static/comment-close.png create mode 100644 released-versions/v0.3.0/_static/comment.png create mode 100644 released-versions/v0.3.0/_static/css/badge_only.css create mode 100644 released-versions/v0.3.0/_static/css/theme.css create mode 100644 released-versions/v0.3.0/_static/doctools.js create mode 100644 released-versions/v0.3.0/_static/down-pressed.png create mode 100644 released-versions/v0.3.0/_static/down.png create mode 100644 released-versions/v0.3.0/_static/file.png create mode 100755 released-versions/v0.3.0/_static/font/fontawesome_webfont.eot create mode 100755 released-versions/v0.3.0/_static/font/fontawesome_webfont.svg create mode 100755 released-versions/v0.3.0/_static/font/fontawesome_webfont.ttf create mode 100755 released-versions/v0.3.0/_static/font/fontawesome_webfont.woff create mode 100644 released-versions/v0.3.0/_static/fonts/FontAwesome.otf create mode 100644 released-versions/v0.3.0/_static/fonts/fontawesome-webfont.eot create mode 100644 released-versions/v0.3.0/_static/fonts/fontawesome-webfont.svg create mode 100644 released-versions/v0.3.0/_static/fonts/fontawesome-webfont.ttf create mode 100644 released-versions/v0.3.0/_static/fonts/fontawesome-webfont.woff create mode 100644 released-versions/v0.3.0/_static/jquery.js create mode 100644 released-versions/v0.3.0/_static/js/theme.js create mode 100644 released-versions/v0.3.0/_static/minus.png create mode 100644 released-versions/v0.3.0/_static/plus.png create mode 100644 released-versions/v0.3.0/_static/pygments.css create mode 100644 released-versions/v0.3.0/_static/searchtools.js create mode 100644 released-versions/v0.3.0/_static/underscore.js create mode 100644 released-versions/v0.3.0/_static/up-pressed.png create mode 100644 released-versions/v0.3.0/_static/up.png create mode 100644 released-versions/v0.3.0/_static/websupport.js create mode 100644 released-versions/v0.3.0/apiref.html create mode 100644 released-versions/v0.3.0/genindex.html create mode 100644 released-versions/v0.3.0/index.html create mode 100644 released-versions/v0.3.0/nghttp2.h.html create mode 100644 released-versions/v0.3.0/nghttp2ver.h.html create mode 100644 released-versions/v0.3.0/objects.inv create mode 100644 released-versions/v0.3.0/package_README.html create mode 100644 released-versions/v0.3.0/search.html create mode 100644 released-versions/v0.3.0/searchindex.js create mode 100644 released-versions/v0.3.0/tutorial-client.html create mode 100644 released-versions/v0.3.0/tutorial-server.html diff --git a/_sources/apiref.txt b/_sources/apiref.txt index a41bb6bf..68c53996 100644 --- a/_sources/apiref.txt +++ b/_sources/apiref.txt @@ -743,8 +743,8 @@ Types (structs, unions and typedefs) This union includes all frames to pass them to various function - calls as nghttp2_frame type. The DATA frame is intentionally - omitted from here. + calls as nghttp2_frame type. The CONTINUATION frame is omitted from + here because the library deals with it internally. .. member:: nghttp2_frame_hd hd @@ -1921,6 +1921,9 @@ Functions written into *\*out* and its length (which is 17) is assigned to *\*outlen*. + For ALPN, refer to + http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 + See http://technotes.googlecode.com/git/nextprotoneg.html for more details about NPN. diff --git a/_sources/index.txt b/_sources/index.txt index 24da1503..4b3f6ff0 100644 --- a/_sources/index.txt +++ b/_sources/index.txt @@ -28,6 +28,7 @@ Contents: Released Versions ================= +* `v0.3.0 `_ `(Download v0.3.0) `_ * `v0.2.0 `_ `(Download v0.2.0) `_ * `v0.1.0 `_ `(Download v0.1.0) `_ diff --git a/_static/css/badge_only.css b/_static/css/badge_only.css index c8235ac2..63b5e22d 100644 --- a/_static/css/badge_only.css +++ b/_static/css/badge_only.css @@ -1 +1 @@ -.font-smooth,.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:fontawesome-webfont;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#fontawesome-webfont") format("svg")}.fa:before{display:inline-block;font-family:fontawesome-webfont;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:"\f02d"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}} +.font-smooth,.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:fontawesome-webfont;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#fontawesome-webfont") format("svg")}.fa:before{display:inline-block;font-family:fontawesome-webfont;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:"\f02d"}.icon-book:before{content:"\f02d"}.fa-caret-down:before{content:"\f0d7"}.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}} diff --git a/_static/css/theme.css b/_static/css/theme.css index 36b8a8a6..7abe9dcd 100644 --- a/_static/css/theme.css +++ b/_static/css/theme.css @@ -1,4 +1,4 @@ *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:0}dfn{font-style:italic}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:20px 0;padding:0}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,code,.rst-content tt,kbd,samp{font-family:monospace,serif;_font-family:"courier new",monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol,dl{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:0.2em 0;background:#ccc;color:#000;padding:0.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.font-smooth,.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.btn,input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"],select,textarea,.wy-tag-input-group,.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a,.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a,.wy-nav-top a{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}/*! * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url("../fonts/fontawesome-webfont.eot?v=4.0.3");src:url("../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff?v=4.0.3") format("woff"),url("../fonts/fontawesome-webfont.ttf?v=4.0.3") format("truetype"),url("../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-tag-input-group .wy-tag .wy-tag-remove,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:0.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:0.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.wy-dropdown .pull-left.caret,.wy-inline-validate.wy-inline-validate-success .pull-left.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .pull-left.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .pull-left.wy-input-context,.wy-inline-validate.wy-inline-validate-info .pull-left.wy-input-context,.wy-tag-input-group .wy-tag .pull-left.wy-tag-remove,.rst-content .pull-left.admonition-title,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content dl dt .pull-left.headerlink{margin-right:.3em}.fa.pull-right,.wy-dropdown .pull-right.caret,.wy-inline-validate.wy-inline-validate-success .pull-right.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .pull-right.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .pull-right.wy-input-context,.wy-inline-validate.wy-inline-validate-info .pull-right.wy-input-context,.wy-tag-input-group .wy-tag .pull-right.wy-tag-remove,.rst-content .pull-right.admonition-title,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content dl dt .pull-right.headerlink{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before,.wy-tag-input-group .wy-tag .wy-tag-remove:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.rst-content .admonition-title:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before,.wy-dropdown .caret:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.btn .fa,.btn .wy-dropdown .caret,.wy-dropdown .btn .caret,.btn .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success .btn .wy-input-context,.btn .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .btn .wy-input-context,.btn .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .btn .wy-input-context,.btn .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info .btn .wy-input-context,.btn .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag .btn .wy-tag-remove,.btn .rst-content .admonition-title,.rst-content .btn .admonition-title,.btn .rst-content h1 .headerlink,.rst-content h1 .btn .headerlink,.btn .rst-content h2 .headerlink,.rst-content h2 .btn .headerlink,.btn .rst-content h3 .headerlink,.rst-content h3 .btn .headerlink,.btn .rst-content h4 .headerlink,.rst-content h4 .btn .headerlink,.btn .rst-content h5 .headerlink,.rst-content h5 .btn .headerlink,.btn .rst-content h6 .headerlink,.rst-content h6 .btn .headerlink,.btn .rst-content dl dt .headerlink,.rst-content dl dt .btn .headerlink,.nav .fa,.nav .wy-dropdown .caret,.wy-dropdown .nav .caret,.nav .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success .nav .wy-input-context,.nav .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .nav .wy-input-context,.nav .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .nav .wy-input-context,.nav .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info .nav .wy-input-context,.nav .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag .nav .wy-tag-remove,.nav .rst-content .admonition-title,.rst-content .nav .admonition-title,.nav .rst-content h1 .headerlink,.rst-content h1 .nav .headerlink,.nav .rst-content h2 .headerlink,.rst-content h2 .nav .headerlink,.nav .rst-content h3 .headerlink,.rst-content h3 .nav .headerlink,.nav .rst-content h4 .headerlink,.rst-content h4 .nav .headerlink,.nav .rst-content h5 .headerlink,.rst-content h5 .nav .headerlink,.nav .rst-content h6 .headerlink,.rst-content h6 .nav .headerlink,.nav .rst-content dl dt .headerlink,.rst-content dl dt .nav .headerlink{display:inline}.btn .fa.fa-large,.btn .wy-dropdown .fa-large.caret,.wy-dropdown .btn .fa-large.caret,.btn .wy-inline-validate.wy-inline-validate-success .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-success .btn .fa-large.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-danger .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .btn .fa-large.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-warning .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .btn .fa-large.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-info .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-info .btn .fa-large.wy-input-context,.btn .wy-tag-input-group .wy-tag .fa-large.wy-tag-remove,.wy-tag-input-group .wy-tag .btn .fa-large.wy-tag-remove,.btn .rst-content .fa-large.admonition-title,.rst-content .btn .fa-large.admonition-title,.btn .rst-content h1 .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.btn .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .btn .fa-large.headerlink,.nav .fa.fa-large,.nav .wy-dropdown .fa-large.caret,.wy-dropdown .nav .fa-large.caret,.nav .wy-inline-validate.wy-inline-validate-success .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-success .nav .fa-large.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-danger .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .nav .fa-large.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-warning .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .nav .fa-large.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-info .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-info .nav .fa-large.wy-input-context,.nav .wy-tag-input-group .wy-tag .fa-large.wy-tag-remove,.wy-tag-input-group .wy-tag .nav .fa-large.wy-tag-remove,.nav .rst-content .fa-large.admonition-title,.rst-content .nav .fa-large.admonition-title,.nav .rst-content h1 .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.nav .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink{line-height:0.9em}.btn .fa.fa-spin,.btn .wy-dropdown .fa-spin.caret,.wy-dropdown .btn .fa-spin.caret,.btn .wy-inline-validate.wy-inline-validate-success .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-success .btn .fa-spin.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-danger .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .btn .fa-spin.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-warning .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .btn .fa-spin.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-info .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-info .btn .fa-spin.wy-input-context,.btn .wy-tag-input-group .wy-tag .fa-spin.wy-tag-remove,.wy-tag-input-group .wy-tag .btn .fa-spin.wy-tag-remove,.btn .rst-content .fa-spin.admonition-title,.rst-content .btn .fa-spin.admonition-title,.btn .rst-content h1 .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.btn .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .btn .fa-spin.headerlink,.nav .fa.fa-spin,.nav .wy-dropdown .fa-spin.caret,.wy-dropdown .nav .fa-spin.caret,.nav .wy-inline-validate.wy-inline-validate-success .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-success .nav .fa-spin.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-danger .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .nav .fa-spin.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-warning .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .nav .fa-spin.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-info .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-info .nav .fa-spin.wy-input-context,.nav .wy-tag-input-group .wy-tag .fa-spin.wy-tag-remove,.wy-tag-input-group .wy-tag .nav .fa-spin.wy-tag-remove,.nav .rst-content .fa-spin.admonition-title,.rst-content .nav .fa-spin.admonition-title,.nav .rst-content h1 .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.nav .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink{display:inline-block}.btn.fa:before,.wy-dropdown .btn.caret:before,.wy-inline-validate.wy-inline-validate-success .btn.wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .btn.wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .btn.wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .btn.wy-input-context:before,.wy-tag-input-group .wy-tag .btn.wy-tag-remove:before,.rst-content .btn.admonition-title:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content dl dt .btn.headerlink:before{opacity:0.5;-webkit-transition:opacity 0.05s ease-in;-moz-transition:opacity 0.05s ease-in;transition:opacity 0.05s ease-in}.btn.fa:hover:before,.wy-dropdown .btn.caret:hover:before,.wy-inline-validate.wy-inline-validate-success .btn.wy-input-context:hover:before,.wy-inline-validate.wy-inline-validate-danger .btn.wy-input-context:hover:before,.wy-inline-validate.wy-inline-validate-warning .btn.wy-input-context:hover:before,.wy-inline-validate.wy-inline-validate-info .btn.wy-input-context:hover:before,.wy-tag-input-group .wy-tag .btn.wy-tag-remove:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content dl dt .btn.headerlink:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .wy-dropdown .caret:before,.wy-dropdown .btn-mini .caret:before,.btn-mini .wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .btn-mini .wy-input-context:before,.btn-mini .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .btn-mini .wy-input-context:before,.btn-mini .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .btn-mini .wy-input-context:before,.btn-mini .wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .btn-mini .wy-input-context:before,.btn-mini .wy-tag-input-group .wy-tag .wy-tag-remove:before,.wy-tag-input-group .wy-tag .btn-mini .wy-tag-remove:before,.btn-mini .rst-content .admonition-title:before,.rst-content .btn-mini .admonition-title:before,.btn-mini .rst-content h1 .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.btn-mini .rst-content dl dt .headerlink:before,.rst-content dl dt .btn-mini .headerlink:before{font-size:14px;vertical-align:-15%}.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso{padding:12px;line-height:24px;margin-bottom:24px}.wy-alert-title,.rst-content .admonition-title{color:#fff;font-weight:bold;display:block;color:#fff;background:transparent;margin:-12px;padding:6px 12px;margin-bottom:12px}.wy-alert.wy-alert-danger,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.rst-content .wy-alert-danger.seealso{background:#fdf3f2}.wy-alert.wy-alert-danger .wy-alert-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .danger .wy-alert-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .danger .admonition-title,.rst-content .error .admonition-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.seealso .admonition-title{background:#f29f97}.wy-alert.wy-alert-warning,.rst-content .wy-alert-warning.note,.rst-content .attention,.rst-content .caution,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.tip,.rst-content .warning,.rst-content .wy-alert-warning.seealso{background:#ffedcc}.wy-alert.wy-alert-warning .wy-alert-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .attention .wy-alert-title,.rst-content .caution .wy-alert-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .attention .admonition-title,.rst-content .caution .admonition-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .warning .admonition-title,.rst-content .wy-alert-warning.seealso .admonition-title{background:#f0b37e}.wy-alert.wy-alert-info,.rst-content .note,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.rst-content .seealso{background:#e7f2fa}.wy-alert.wy-alert-info .wy-alert-title,.rst-content .note .wy-alert-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .seealso .wy-alert-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.rst-content .note .admonition-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .seealso .admonition-title{background:#6ab0de}.wy-alert.wy-alert-success,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.warning,.rst-content .wy-alert-success.seealso{background:#dbfaf4}.wy-alert.wy-alert-success .wy-alert-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .hint .wy-alert-title,.rst-content .important .wy-alert-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .hint .admonition-title,.rst-content .important .admonition-title,.rst-content .tip .admonition-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.seealso .admonition-title{background:#1abc9c}.wy-alert.wy-alert-neutral,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.rst-content .wy-alert-neutral.seealso{background:#f3f6f6}.wy-alert.wy-alert-neutral strong,.rst-content .wy-alert-neutral.note strong,.rst-content .wy-alert-neutral.attention strong,.rst-content .wy-alert-neutral.caution strong,.rst-content .wy-alert-neutral.danger strong,.rst-content .wy-alert-neutral.error strong,.rst-content .wy-alert-neutral.hint strong,.rst-content .wy-alert-neutral.important strong,.rst-content .wy-alert-neutral.tip strong,.rst-content .wy-alert-neutral.warning strong,.rst-content .wy-alert-neutral.seealso strong{color:#404040}.wy-alert.wy-alert-neutral a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.rst-content .wy-alert-neutral.seealso a{color:#2980b9}.wy-tray-container{position:fixed;top:-50px;left:0;width:100%;-webkit-transition:top 0.2s ease-in;-moz-transition:top 0.2s ease-in;transition:top 0.2s ease-in}.wy-tray-container.on{top:0}.wy-tray-container li{display:none;width:100%;background:#343131;padding:12px 24px;color:#fff;margin-bottom:6px;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1),0px -1px 2px -1px rgba(255,255,255,0.5) inset}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.btn{display:inline-block;*display:inline;zoom:1;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-size:100%;padding:6px 12px;color:#fff;border:1px solid rgba(0,0,0,0.1);border-bottom:solid 3px rgba(0,0,0,0.1);background-color:#27ae60;text-decoration:none;font-weight:500;box-shadow:0px 1px 2px -1px rgba(255,255,255,0.5) inset;-webkit-transition:all 0.1s linear;-moz-transition:all 0.1s linear;transition:all 0.1s linear;outline-none:false}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;color:#fff;outline:0}.btn:active{border-top:solid 3px rgba(0,0,0,0.1);border-bottom:solid 1px rgba(0,0,0,0.1);box-shadow:0px 1px 2px -1px rgba(0,0,0,0.5) inset}.btn[disabled]{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn:visited{color:#fff}.btn-disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled:hover,.btn-disabled:focus,.btn-disabled:active{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9 !important}.btn-info:hover{background-color:#2e8ece !important}.btn-neutral{background-color:#f3f6f6 !important;color:#404040 !important}.btn-neutral:hover{background-color:#e5ebeb !important;color:#404040}.btn-neutral:visited{color:#404040 !important}.btn-success{background-color:#27ae60 !important}.btn-success:hover{background-color:#295 !important}.btn-danger{background-color:#e74c3c !important}.btn-danger:hover{background-color:#ea6153 !important}.btn-warning{background-color:#e67e22 !important}.btn-warning:hover{background-color:#e98b39 !important}.btn-invert{background-color:#343131}.btn-invert:hover{background-color:#413d3d !important}.btn-link{background-color:transparent !important;color:#2980b9;border-color:transparent;box-shadow:none}.btn-link:hover{background-color:transparent !important;color:#409ad5;border-color:transparent;box-shadow:none}.btn-link:active{background-color:transparent !important;border-color:transparent;border-top:solid 1px transparent;border-bottom:solid 3px transparent;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:before,.wy-btn-group:after{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-menu{position:absolute;top:100%;left:0;display:none;float:left;min-width:100%;background:#fcfcfc;z-index:100;border:solid 1px #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,0.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:solid 1px #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type="search"]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned input,.wy-form-aligned textarea,.wy-form-aligned select,.wy-form-aligned .wy-help-inline,.wy-form-aligned label{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:0.5em 1em 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:0.5em}fieldset{border:0;margin:0;padding:0}legend{display:block;width:100%;border:0;padding:0;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label{display:block;margin:0 0 0.3125em 0;color:#999;font-size:90%}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button{-webkit-appearance:button;cursor:pointer;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}input[type="datetime-local"]{padding:0.34375em 0.625em}input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;margin-right:0.3125em;*height:13px;*width:13px}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input[type="text"]:focus,input[type="password"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus{outline:0;outline:thin dotted \9;border-color:#333}input.no-focus:focus{border-color:#ccc !important}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type="text"][disabled],input[type="password"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="color"][disabled]{cursor:not-allowed;background-color:#f3f6f6;color:#cad2d3}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e74c3c}input[type="file"]:focus:invalid:focus,input[type="radio"]:focus:invalid:focus,input[type="checkbox"]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%}select,textarea{padding:0.5em 0.625em;display:inline-block;border:1px solid #ccc;font-size:0.8em;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#fff;color:#cad2d3;border-color:transparent}.wy-checkbox,.wy-radio{margin:0.5em 0;color:#404040;display:block}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{padding:6px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:solid 1px #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:0.5em 0.625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.wy-control-group{margin-bottom:24px;*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type="text"],.wy-control-group.wy-control-group-error input[type="password"],.wy-control-group.wy-control-group-error input[type="email"],.wy-control-group.wy-control-group-error input[type="url"],.wy-control-group.wy-control-group-error input[type="date"],.wy-control-group.wy-control-group-error input[type="month"],.wy-control-group.wy-control-group-error input[type="time"],.wy-control-group.wy-control-group-error input[type="datetime"],.wy-control-group.wy-control-group-error input[type="datetime-local"],.wy-control-group.wy-control-group-error input[type="week"],.wy-control-group.wy-control-group-error input[type="number"],.wy-control-group.wy-control-group-error input[type="search"],.wy-control-group.wy-control-group-error input[type="tel"],.wy-control-group.wy-control-group-error input[type="color"]{border:solid 2px #e74c3c}.wy-control-group.wy-control-group-error textarea{border:solid 2px #e74c3c}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full input[type="text"],.wy-control-group .wy-form-full input[type="password"],.wy-control-group .wy-form-full input[type="email"],.wy-control-group .wy-form-full input[type="url"],.wy-control-group .wy-form-full input[type="date"],.wy-control-group .wy-form-full input[type="month"],.wy-control-group .wy-form-full input[type="time"],.wy-control-group .wy-form-full input[type="datetime"],.wy-control-group .wy-form-full input[type="datetime-local"],.wy-control-group .wy-form-full input[type="week"],.wy-control-group .wy-form-full input[type="number"],.wy-control-group .wy-form-full input[type="search"],.wy-control-group .wy-form-full input[type="tel"],.wy-control-group .wy-form-full input[type="color"],.wy-control-group .wy-form-halves input[type="text"],.wy-control-group .wy-form-halves input[type="password"],.wy-control-group .wy-form-halves input[type="email"],.wy-control-group .wy-form-halves input[type="url"],.wy-control-group .wy-form-halves input[type="date"],.wy-control-group .wy-form-halves input[type="month"],.wy-control-group .wy-form-halves input[type="time"],.wy-control-group .wy-form-halves input[type="datetime"],.wy-control-group .wy-form-halves input[type="datetime-local"],.wy-control-group .wy-form-halves input[type="week"],.wy-control-group .wy-form-halves input[type="number"],.wy-control-group .wy-form-halves input[type="search"],.wy-control-group .wy-form-halves input[type="tel"],.wy-control-group .wy-form-halves input[type="color"],.wy-control-group .wy-form-thirds input[type="text"],.wy-control-group .wy-form-thirds input[type="password"],.wy-control-group .wy-form-thirds input[type="email"],.wy-control-group .wy-form-thirds input[type="url"],.wy-control-group .wy-form-thirds input[type="date"],.wy-control-group .wy-form-thirds input[type="month"],.wy-control-group .wy-form-thirds input[type="time"],.wy-control-group .wy-form-thirds input[type="datetime"],.wy-control-group .wy-form-thirds input[type="datetime-local"],.wy-control-group .wy-form-thirds input[type="week"],.wy-control-group .wy-form-thirds input[type="number"],.wy-control-group .wy-form-thirds input[type="search"],.wy-control-group .wy-form-thirds input[type="tel"],.wy-control-group .wy-form-thirds input[type="color"]{width:100%}.wy-control-group .wy-form-full{display:block;float:left;margin-right:2.35765%;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{display:block;float:left;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child{margin-right:0}.wy-control-group .wy-form-halves:nth-child(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-child(2n+1){clear:left}.wy-control-group .wy-form-thirds{display:block;float:left;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child{margin-right:0}.wy-control-group .wy-form-thirds:nth-child(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-child(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control{margin:0.5em 0 0 0;font-size:90%}.wy-control-group.fluid-input input[type="text"],.wy-control-group.fluid-input input[type="password"],.wy-control-group.fluid-input input[type="email"],.wy-control-group.fluid-input input[type="url"],.wy-control-group.fluid-input input[type="date"],.wy-control-group.fluid-input input[type="month"],.wy-control-group.fluid-input input[type="time"],.wy-control-group.fluid-input input[type="datetime"],.wy-control-group.fluid-input input[type="datetime-local"],.wy-control-group.fluid-input input[type="week"],.wy-control-group.fluid-input input[type="number"],.wy-control-group.fluid-input input[type="search"],.wy-control-group.fluid-input input[type="tel"],.wy-control-group.fluid-input input[type="color"]{width:100%}.wy-form-message-inline{display:inline-block;padding-left:0.3em;color:#666;vertical-align:middle;font-size:90%}.wy-form-message{display:block;color:#ccc;font-size:70%;margin-top:0.3125em;font-style:italic}.wy-tag-input-group{padding:4px 4px 0px 4px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;background:#fff;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}.wy-tag-input-group .wy-tag{display:inline-block;background-color:rgba(0,0,0,0.1);padding:0.5em 0.625em;border-radius:2px;position:relative;margin-bottom:4px}.wy-tag-input-group .wy-tag .wy-tag-remove{color:#ccc;margin-left:5px}.wy-tag-input-group .wy-tag .wy-tag-remove:hover{color:#e74c3c}.wy-tag-input-group label{margin-left:5px;display:inline-block;margin-bottom:0}.wy-tag-input-group input{border:none;font-size:100%;margin-bottom:4px;box-shadow:none}.wy-form-upload{border:solid 1px #ccc;border-bottom:solid 3px #ccc;background-color:#f3f6f6;padding:24px;display:inline-block;text-align:center;cursor:pointer;color:#404040;-webkit-transition:border-color 0.1s ease-in;-moz-transition:border-color 0.1s ease-in;transition:border-color 0.1s ease-in;*zoom:1}.wy-form-upload:before,.wy-form-upload:after{display:table;content:""}.wy-form-upload:after{clear:both}@media screen and (max-width: 480px){.wy-form-upload{width:100%}}.wy-form-upload .image-drop{display:none}.wy-form-upload .image-desktop{display:none}.wy-form-upload .image-loading{display:none}.wy-form-upload .wy-form-upload-icon{display:block;font-size:32px;color:#b3b3b3}.wy-form-upload .image-drop .wy-form-upload-icon{color:#27ae60}.wy-form-upload p{font-size:90%}.wy-form-upload .wy-form-upload-image{float:left;margin-right:24px}@media screen and (max-width: 480px){.wy-form-upload .wy-form-upload-image{width:100%;margin-bottom:24px}}.wy-form-upload img{max-width:125px;max-height:125px;opacity:0.9;-webkit-transition:opacity 0.1s ease-in;-moz-transition:opacity 0.1s ease-in;transition:opacity 0.1s ease-in}.wy-form-upload .wy-form-upload-content{float:left}@media screen and (max-width: 480px){.wy-form-upload .wy-form-upload-content{width:100%}}.wy-form-upload:hover{border-color:#b3b3b3;color:#404040}.wy-form-upload:hover .image-desktop{display:block}.wy-form-upload:hover .image-drag{display:none}.wy-form-upload:hover img{opacity:1}.wy-form-upload:active{border-top:solid 3px #ccc;border-bottom:solid 1px #ccc}.wy-form-upload.wy-form-upload-big{width:100%;text-align:center;padding:72px}.wy-form-upload.wy-form-upload-big .wy-form-upload-content{float:none}.wy-form-upload.wy-form-upload-file p{margin-bottom:0}.wy-form-upload.wy-form-upload-file .wy-form-upload-icon{display:inline-block;font-size:inherit}.wy-form-upload.wy-form-upload-drop{background-color:#ddf7e8}.wy-form-upload.wy-form-upload-drop .image-drop{display:block}.wy-form-upload.wy-form-upload-drop .image-desktop{display:none}.wy-form-upload.wy-form-upload-drop .image-drag{display:none}.wy-form-upload.wy-form-upload-loading .image-drag{display:none}.wy-form-upload.wy-form-upload-loading .image-desktop{display:none}.wy-form-upload.wy-form-upload-loading .image-loading{display:block}.wy-form-upload.wy-form-upload-loading .wy-input-prefix{display:none}.wy-form-upload.wy-form-upload-loading p{margin-bottom:0}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}.wy-form-gallery-manage{margin-left:-12px;margin-right:-12px}.wy-form-gallery-manage li{float:left;padding:12px;width:20%;cursor:pointer}@media screen and (max-width: 768px){.wy-form-gallery-manage li{width:25%}}@media screen and (max-width: 480px){.wy-form-gallery-manage li{width:50%}}.wy-form-gallery-manage li:active{cursor:move}.wy-form-gallery-manage li>a{padding:12px;background-color:#fff;border:solid 1px #e1e4e5;border-bottom:solid 3px #e1e4e5;display:inline-block;-webkit-transition:all 0.1s ease-in;-moz-transition:all 0.1s ease-in;transition:all 0.1s ease-in}.wy-form-gallery-manage li>a:active{border:solid 1px #ccc;border-top:solid 3px #ccc}.wy-form-gallery-manage img{width:100%;-webkit-transition:all 0.05s ease-in;-moz-transition:all 0.05s ease-in;transition:all 0.05s ease-in}li.wy-form-gallery-edit{position:relative;color:#fff;padding:24px;width:100%;display:block;background-color:#343131;border-radius:4px}li.wy-form-gallery-edit .arrow{position:absolute;display:block;top:-50px;left:50%;margin-left:-25px;z-index:500;height:0;width:0;border-color:transparent;border-style:solid;border-width:25px;border-bottom-color:#343131}@media only screen and (max-width: 480px){.wy-form button[type="submit"]{margin:0.7em 0 0}.wy-form input[type="text"],.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0.3em;display:block}.wy-form label{margin-bottom:0.3em;display:block}.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:0.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-controls{margin:1.5em 0 0 0}.wy-form .wy-help-inline,.wy-form-message-inline,.wy-form-message{display:block;font-size:80%;padding:0.2em 0 0.8em}}@media screen and (max-width: 768px){.tablet-hide{display:none}}@media screen and (max-width: 480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.wy-grid-one-col{*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;max-width:1066px;margin-top:1.618em}.wy-grid-one-col:before,.wy-grid-one-col:after{display:table;content:""}.wy-grid-one-col:after{clear:both}.wy-grid-one-col section{display:block;float:left;margin-right:2.35765%;width:100%;background:#fcfcfc;padding:1.618em;margin-right:0}.wy-grid-one-col section:last-child{margin-right:0}.wy-grid-index-card{*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;max-width:460px;margin-top:1.618em;background:#fcfcfc;padding:1.618em}.wy-grid-index-card:before,.wy-grid-index-card:after{display:table;content:""}.wy-grid-index-card:after{clear:both}.wy-grid-index-card header,.wy-grid-index-card section,.wy-grid-index-card aside{display:block;float:left;margin-right:2.35765%;width:100%}.wy-grid-index-card header:last-child,.wy-grid-index-card section:last-child,.wy-grid-index-card aside:last-child{margin-right:0}.wy-grid-index-card.twocol{max-width:768px}.wy-grid-index-card.twocol section{display:block;float:left;margin-right:2.35765%;width:48.82117%}.wy-grid-index-card.twocol section:last-child{margin-right:0}.wy-grid-index-card.twocol aside{display:block;float:left;margin-right:2.35765%;width:48.82117%}.wy-grid-index-card.twocol aside:last-child{margin-right:0}.wy-grid-search-filter{*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;margin-bottom:24px}.wy-grid-search-filter:before,.wy-grid-search-filter:after{display:table;content:""}.wy-grid-search-filter:after{clear:both}.wy-grid-search-filter .wy-grid-search-filter-input{display:block;float:left;margin-right:2.35765%;width:74.41059%}.wy-grid-search-filter .wy-grid-search-filter-input:last-child{margin-right:0}.wy-grid-search-filter .wy-grid-search-filter-btn{display:block;float:left;margin-right:2.35765%;width:23.23176%}.wy-grid-search-filter .wy-grid-search-filter-btn:last-child{margin-right:0}.wy-table,.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.wy-table caption,.rst-content table.docutils caption,.rst-content table.field-list caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td,.wy-table th,.rst-content table.docutils th,.rst-content table.field-list th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.wy-table td:first-child,.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.wy-table th:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.wy-table thead,.rst-content table.docutils thead,.rst-content table.field-list thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.wy-table thead th,.rst-content table.docutils thead th,.rst-content table.field-list thead th{font-weight:bold;border-bottom:solid 2px #e1e4e5}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.wy-table td p,.rst-content table.docutils td p,.rst-content table.field-list td p{line-height:18px;margin-bottom:0}.wy-table .wy-table-cell-min,.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min{width:1%;padding-right:0}.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:gray;font-size:90%}.wy-table-tertiary{color:gray;font-size:80%}.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td,.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:#f3f6f6}.wy-table-backed{background-color:#f3f6f6}.wy-table-bordered-all,.rst-content table.docutils{border:1px solid #e1e4e5}.wy-table-bordered-all td,.rst-content table.docutils td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.wy-table-bordered-all tbody>tr:last-child td,.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0 !important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}html{height:100%;overflow-x:hidden}body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#404040;min-height:100%;overflow-x:hidden;background:#edf0f2}a{color:#2980b9;text-decoration:none}a:hover{color:#3091d1}a:visited{color:#9b59b6}.link-danger{color:#e74c3c}.link-danger:hover{color:#d62c1a}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}small{font-size:80%}code,.rst-content tt{white-space:nowrap;max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:0 5px;font-family:"Incosolata","Consolata","Monaco",monospace;color:#e74c3c;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.full-width{width:100%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul{list-style:disc;line-height:24px;margin-bottom:24px}.wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li{list-style:disc;margin-left:24px}.wy-plain-list-disc li ul,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li ul{margin-bottom:0}.wy-plain-list-disc li li,.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li{list-style:circle}.wy-plain-list-disc li li li,.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li{list-style:square}.wy-plain-list-decimal,.rst-content .section ol,.rst-content ol.arabic{list-style:decimal;line-height:24px;margin-bottom:24px}.wy-plain-list-decimal li,.rst-content .section ol li,.rst-content ol.arabic li{list-style:decimal;margin-left:24px}.wy-type-large{font-size:120%}.wy-type-normal{font-size:100%}.wy-type-small{font-size:100%}.wy-type-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980b9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27ae60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#e74c3c !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}.codeblock-example{border:1px solid #e1e4e5;border-bottom:none;padding:24px;padding-top:48px;font-weight:500;background:#fff;position:relative}.codeblock-example:after{content:"Example";position:absolute;top:0px;left:0px;background:#9b59b6;color:#fff;padding:6px 12px}.codeblock-example.prettyprint-example-only{border:1px solid #e1e4e5;margin-bottom:24px}.codeblock,.rst-content .literal-block,div[class^='highlight']{border:1px solid #e1e4e5;padding:0px;overflow-x:auto;background:#fff;margin:1px 0 24px 0}.codeblock div[class^='highlight'],.rst-content .literal-block div[class^='highlight'],div[class^='highlight'] div[class^='highlight']{border:none;background:none;margin:0}div[class^='highlight'] td.code{width:100%}.linenodiv pre{border-right:solid 1px #e6e9ea;margin:0;padding:12px 12px;font-family:"Incosolata","Consolata","Monaco",monospace;font-size:12px;line-height:1.5;color:#d9d9d9}div[class^='highlight'] pre{white-space:pre;margin:0;padding:12px 12px;font-family:"Incosolata","Consolata","Monaco",monospace;font-size:12px;line-height:1.5;display:block;overflow:auto;color:#404040}pre.literal-block{@extends .codeblock;}@media print{.codeblock,.rst-content .literal-block,div[class^='highlight'],div[class^='highlight'] pre{white-space:pre-wrap}}.hll{background-color:#ffc;margin:0 -12px;padding:0 12px;display:block}.c{color:#998;font-style:italic}.err{color:#a61717;background-color:#e3d2d2}.k{font-weight:bold}.o{font-weight:bold}.cm{color:#998;font-style:italic}.cp{color:#999;font-weight:bold}.c1{color:#998;font-style:italic}.cs{color:#999;font-weight:bold;font-style:italic}.gd{color:#000;background-color:#fdd}.gd .x{color:#000;background-color:#faa}.ge{font-style:italic}.gr{color:#a00}.gh{color:#999}.gi{color:#000;background-color:#dfd}.gi .x{color:#000;background-color:#afa}.go{color:#888}.gp{color:#555}.gs{font-weight:bold}.gu{color:purple;font-weight:bold}.gt{color:#a00}.kc{font-weight:bold}.kd{font-weight:bold}.kn{font-weight:bold}.kp{font-weight:bold}.kr{font-weight:bold}.kt{color:#458;font-weight:bold}.m{color:#099}.s{color:#d14}.n{color:#333}.na{color:teal}.nb{color:#0086b3}.nc{color:#458;font-weight:bold}.no{color:teal}.ni{color:purple}.ne{color:#900;font-weight:bold}.nf{color:#900;font-weight:bold}.nn{color:#555}.nt{color:navy}.nv{color:teal}.ow{font-weight:bold}.w{color:#bbb}.mf{color:#099}.mh{color:#099}.mi{color:#099}.mo{color:#099}.sb{color:#d14}.sc{color:#d14}.sd{color:#d14}.s2{color:#d14}.se{color:#d14}.sh{color:#d14}.si{color:#d14}.sx{color:#d14}.sr{color:#009926}.s1{color:#d14}.ss{color:#990073}.bp{color:#999}.vc{color:teal}.vg{color:teal}.vi{color:teal}.il{color:#099}.gc{color:#999;background-color:#eaf2f5}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width: 480px){.wy-breadcrumbs-extra{display:none}.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:before,.wy-menu-horiz:after{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz ul,.wy-menu-horiz li{display:inline-block}.wy-menu-horiz li:hover{background:rgba(255,255,255,0.1)}.wy-menu-horiz li.divide-left{border-left:solid 1px #404040}.wy-menu-horiz li.divide-right{border-right:solid 1px #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical header{height:32px;display:inline-block;line-height:32px;padding:0 1.618em;display:block;font-weight:bold;text-transform:uppercase;font-size:80%;color:#2980b9;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:solid 1px #404040}.wy-menu-vertical li.divide-bottom{border-bottom:solid 1px #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:gray;border-right:solid 1px #c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a{color:#404040;padding:0.4045em 1.618em;font-weight:bold;position:relative;background:#fcfcfc;border:none;border-bottom:solid 1px #c9c9c9;border-top:solid 1px #c9c9c9;padding-left:1.618em -4px}.wy-menu-vertical li.on a:hover,.wy-menu-vertical li.current>a:hover{background:#fcfcfc}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical .local-toc li ul{display:block}.wy-menu-vertical li ul li a{margin-bottom:0;color:#b3b3b3;font-weight:normal}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:0.4045em 1.618em;display:block;position:relative;font-size:90%;color:#b3b3b3}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-side-nav-search{z-index:200;background-color:#2980b9;text-align:center;padding:0.809em;display:block;color:#fcfcfc;margin-bottom:0.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto 0.809em auto;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a{color:#fcfcfc;font-size:100%;font-weight:bold;display:inline-block;padding:4px 6px;margin-bottom:0.809em}.wy-side-nav-search>a:hover,.wy-side-nav-search .wy-dropdown>a:hover{background:rgba(255,255,255,0.1)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all 0.2s ease-in;-moz-transition:all 0.2s ease-in;transition:all 0.2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:left repeat-y #fcfcfc;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC);background-size:300px 1px}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:absolute;top:0;left:0;width:300px;overflow:hidden;min-height:100%;background:#343131;z-index:200}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:0.4045em 0.809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:before,.wy-nav-top:after{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:bold}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,0.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:#999}footer p{margin-bottom:12px}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:before,.rst-footer-buttons:after{display:table;content:""}.rst-footer-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:solid 1px #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:solid 1px #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:gray;font-size:90%}@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width: 1400px){.wy-nav-content-wrap{background:rgba(0,0,0,0.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.wy-nav-side{display:none}.wy-nav-content-wrap{margin-left:0}}nav.stickynav{position:fixed;top:0}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .wy-dropdown .caret,.wy-dropdown .rst-versions .rst-current-version .caret,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag .rst-versions .rst-current-version .wy-tag-remove,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-content dl dt .rst-versions .rst-current-version .headerlink{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}}.rst-content img{max-width:100%;height:auto !important}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img{margin-bottom:24px}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content .note .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .tip .last,.rst-content .warning .last,.rst-content .seealso .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,0.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent !important;border-color:rgba(0,0,0,0.1) !important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .line-block{margin-left:24px}.rst-content .topic-title{font-weight:bold;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0px 0px 24px 24px}.rst-content .align-left{float:left;margin:0px 24px 24px 0px}.rst-content .align-center{margin:auto;display:block}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink{display:none;visibility:hidden;font-size:14px}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after{visibility:visible;content:"\f0c1";font-family:fontawesome-webfont;display:inline-block}.rst-content h1:hover .headerlink,.rst-content h2:hover .headerlink,.rst-content h3:hover .headerlink,.rst-content h4:hover .headerlink,.rst-content h5:hover .headerlink,.rst-content h6:hover .headerlink,.rst-content dl dt:hover .headerlink{display:inline-block}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:solid 1px #e1e4e5}.rst-content .sidebar p,.rst-content .sidebar ul,.rst-content .sidebar dl{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;font-weight:bold;background:#e1e4e5;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;display:inline-block;font-weight:bold;padding:0 6px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:super;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:#999}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent !important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.field-list{border:none}.rst-content table.field-list td{border:none;padding-top:5px}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left;padding-left:0}.rst-content tt{color:#000}.rst-content tt big,.rst-content tt em{font-size:100% !important;line-height:normal}.rst-content tt .xref,a .rst-content tt{font-weight:bold}.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:bold}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px !important}.rst-content dl dd{margin:0 0 12px 24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:inline-block;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:solid 3px #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 3px #ccc;background:#f0f0f0;color:gray}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) tt{font-weight:bold}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname{background-color:transparent;border:none;padding:0;font-size:100% !important}.rst-content dl:not(.docutils) tt.descname{font-weight:bold}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:bold}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-link,.rst-content .viewcode-back{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}@media screen and (max-width: 480px){.rst-content .sidebar{width:100%}}span[id*='MathJax-Span']{color:#404040} + */@font-face{font-family:'FontAwesome';src:url("../fonts/fontawesome-webfont.eot?v=4.0.3");src:url("../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff?v=4.0.3") format("woff"),url("../fonts/fontawesome-webfont.ttf?v=4.0.3") format("truetype"),url("../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-tag-input-group .wy-tag .wy-tag-remove,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.icon{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:0.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:0.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.wy-dropdown .pull-left.caret,.wy-inline-validate.wy-inline-validate-success .pull-left.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .pull-left.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .pull-left.wy-input-context,.wy-inline-validate.wy-inline-validate-info .pull-left.wy-input-context,.wy-tag-input-group .wy-tag .pull-left.wy-tag-remove,.rst-content .pull-left.admonition-title,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content dl dt .pull-left.headerlink,.pull-left.icon{margin-right:.3em}.fa.pull-right,.wy-dropdown .pull-right.caret,.wy-inline-validate.wy-inline-validate-success .pull-right.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .pull-right.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .pull-right.wy-input-context,.wy-inline-validate.wy-inline-validate-info .pull-right.wy-input-context,.wy-tag-input-group .wy-tag .pull-right.wy-tag-remove,.rst-content .pull-right.admonition-title,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content dl dt .pull-right.headerlink,.pull-right.icon{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before,.icon-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before,.wy-tag-input-group .wy-tag .wy-tag-remove:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before,.icon-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.rst-content .admonition-title:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before,.icon-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before,.icon-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:"\f0a8"}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before,.wy-dropdown .caret:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before,.icon-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.btn .fa,.btn .wy-dropdown .caret,.wy-dropdown .btn .caret,.btn .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success .btn .wy-input-context,.btn .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .btn .wy-input-context,.btn .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .btn .wy-input-context,.btn .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info .btn .wy-input-context,.btn .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag .btn .wy-tag-remove,.btn .rst-content .admonition-title,.rst-content .btn .admonition-title,.btn .rst-content h1 .headerlink,.rst-content h1 .btn .headerlink,.btn .rst-content h2 .headerlink,.rst-content h2 .btn .headerlink,.btn .rst-content h3 .headerlink,.rst-content h3 .btn .headerlink,.btn .rst-content h4 .headerlink,.rst-content h4 .btn .headerlink,.btn .rst-content h5 .headerlink,.rst-content h5 .btn .headerlink,.btn .rst-content h6 .headerlink,.rst-content h6 .btn .headerlink,.btn .rst-content dl dt .headerlink,.rst-content dl dt .btn .headerlink,.btn .icon,.nav .fa,.nav .wy-dropdown .caret,.wy-dropdown .nav .caret,.nav .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success .nav .wy-input-context,.nav .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .nav .wy-input-context,.nav .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .nav .wy-input-context,.nav .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info .nav .wy-input-context,.nav .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag .nav .wy-tag-remove,.nav .rst-content .admonition-title,.rst-content .nav .admonition-title,.nav .rst-content h1 .headerlink,.rst-content h1 .nav .headerlink,.nav .rst-content h2 .headerlink,.rst-content h2 .nav .headerlink,.nav .rst-content h3 .headerlink,.rst-content h3 .nav .headerlink,.nav .rst-content h4 .headerlink,.rst-content h4 .nav .headerlink,.nav .rst-content h5 .headerlink,.rst-content h5 .nav .headerlink,.nav .rst-content h6 .headerlink,.rst-content h6 .nav .headerlink,.nav .rst-content dl dt .headerlink,.rst-content dl dt .nav .headerlink,.nav .icon{display:inline}.btn .fa.fa-large,.btn .wy-dropdown .fa-large.caret,.wy-dropdown .btn .fa-large.caret,.btn .wy-inline-validate.wy-inline-validate-success .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-success .btn .fa-large.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-danger .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .btn .fa-large.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-warning .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .btn .fa-large.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-info .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-info .btn .fa-large.wy-input-context,.btn .wy-tag-input-group .wy-tag .fa-large.wy-tag-remove,.wy-tag-input-group .wy-tag .btn .fa-large.wy-tag-remove,.btn .rst-content .fa-large.admonition-title,.rst-content .btn .fa-large.admonition-title,.btn .rst-content h1 .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.btn .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .btn .fa-large.headerlink,.btn .fa-large.icon,.nav .fa.fa-large,.nav .wy-dropdown .fa-large.caret,.wy-dropdown .nav .fa-large.caret,.nav .wy-inline-validate.wy-inline-validate-success .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-success .nav .fa-large.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-danger .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .nav .fa-large.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-warning .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .nav .fa-large.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-info .fa-large.wy-input-context,.wy-inline-validate.wy-inline-validate-info .nav .fa-large.wy-input-context,.nav .wy-tag-input-group .wy-tag .fa-large.wy-tag-remove,.wy-tag-input-group .wy-tag .nav .fa-large.wy-tag-remove,.nav .rst-content .fa-large.admonition-title,.rst-content .nav .fa-large.admonition-title,.nav .rst-content h1 .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.nav .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.nav .fa-large.icon{line-height:0.9em}.btn .fa.fa-spin,.btn .wy-dropdown .fa-spin.caret,.wy-dropdown .btn .fa-spin.caret,.btn .wy-inline-validate.wy-inline-validate-success .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-success .btn .fa-spin.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-danger .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .btn .fa-spin.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-warning .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .btn .fa-spin.wy-input-context,.btn .wy-inline-validate.wy-inline-validate-info .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-info .btn .fa-spin.wy-input-context,.btn .wy-tag-input-group .wy-tag .fa-spin.wy-tag-remove,.wy-tag-input-group .wy-tag .btn .fa-spin.wy-tag-remove,.btn .rst-content .fa-spin.admonition-title,.rst-content .btn .fa-spin.admonition-title,.btn .rst-content h1 .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.btn .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .btn .fa-spin.headerlink,.btn .fa-spin.icon,.nav .fa.fa-spin,.nav .wy-dropdown .fa-spin.caret,.wy-dropdown .nav .fa-spin.caret,.nav .wy-inline-validate.wy-inline-validate-success .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-success .nav .fa-spin.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-danger .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-danger .nav .fa-spin.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-warning .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-warning .nav .fa-spin.wy-input-context,.nav .wy-inline-validate.wy-inline-validate-info .fa-spin.wy-input-context,.wy-inline-validate.wy-inline-validate-info .nav .fa-spin.wy-input-context,.nav .wy-tag-input-group .wy-tag .fa-spin.wy-tag-remove,.wy-tag-input-group .wy-tag .nav .fa-spin.wy-tag-remove,.nav .rst-content .fa-spin.admonition-title,.rst-content .nav .fa-spin.admonition-title,.nav .rst-content h1 .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.nav .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.nav .fa-spin.icon{display:inline-block}.btn.fa:before,.wy-dropdown .btn.caret:before,.wy-inline-validate.wy-inline-validate-success .btn.wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .btn.wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .btn.wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .btn.wy-input-context:before,.wy-tag-input-group .wy-tag .btn.wy-tag-remove:before,.rst-content .btn.admonition-title:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content dl dt .btn.headerlink:before,.btn.icon:before{opacity:0.5;-webkit-transition:opacity 0.05s ease-in;-moz-transition:opacity 0.05s ease-in;transition:opacity 0.05s ease-in}.btn.fa:hover:before,.wy-dropdown .btn.caret:hover:before,.wy-inline-validate.wy-inline-validate-success .btn.wy-input-context:hover:before,.wy-inline-validate.wy-inline-validate-danger .btn.wy-input-context:hover:before,.wy-inline-validate.wy-inline-validate-warning .btn.wy-input-context:hover:before,.wy-inline-validate.wy-inline-validate-info .btn.wy-input-context:hover:before,.wy-tag-input-group .wy-tag .btn.wy-tag-remove:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.btn.icon:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .wy-dropdown .caret:before,.wy-dropdown .btn-mini .caret:before,.btn-mini .wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .btn-mini .wy-input-context:before,.btn-mini .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .btn-mini .wy-input-context:before,.btn-mini .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .btn-mini .wy-input-context:before,.btn-mini .wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .btn-mini .wy-input-context:before,.btn-mini .wy-tag-input-group .wy-tag .wy-tag-remove:before,.wy-tag-input-group .wy-tag .btn-mini .wy-tag-remove:before,.btn-mini .rst-content .admonition-title:before,.rst-content .btn-mini .admonition-title:before,.btn-mini .rst-content h1 .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.btn-mini .rst-content dl dt .headerlink:before,.rst-content dl dt .btn-mini .headerlink:before,.btn-mini .icon:before{font-size:14px;vertical-align:-15%}.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso{padding:12px;line-height:24px;margin-bottom:24px}.wy-alert-title,.rst-content .admonition-title{color:#fff;font-weight:bold;display:block;color:#fff;background:transparent;margin:-12px;padding:6px 12px;margin-bottom:12px}.wy-alert.wy-alert-danger,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.rst-content .wy-alert-danger.seealso{background:#fdf3f2}.wy-alert.wy-alert-danger .wy-alert-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .danger .wy-alert-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .danger .admonition-title,.rst-content .error .admonition-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.seealso .admonition-title{background:#f29f97}.wy-alert.wy-alert-warning,.rst-content .wy-alert-warning.note,.rst-content .attention,.rst-content .caution,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.tip,.rst-content .warning,.rst-content .wy-alert-warning.seealso{background:#ffedcc}.wy-alert.wy-alert-warning .wy-alert-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .attention .wy-alert-title,.rst-content .caution .wy-alert-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .attention .admonition-title,.rst-content .caution .admonition-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .warning .admonition-title,.rst-content .wy-alert-warning.seealso .admonition-title{background:#f0b37e}.wy-alert.wy-alert-info,.rst-content .note,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.rst-content .seealso{background:#e7f2fa}.wy-alert.wy-alert-info .wy-alert-title,.rst-content .note .wy-alert-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .seealso .wy-alert-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.rst-content .note .admonition-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .seealso .admonition-title{background:#6ab0de}.wy-alert.wy-alert-success,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.warning,.rst-content .wy-alert-success.seealso{background:#dbfaf4}.wy-alert.wy-alert-success .wy-alert-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .hint .wy-alert-title,.rst-content .important .wy-alert-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .hint .admonition-title,.rst-content .important .admonition-title,.rst-content .tip .admonition-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.seealso .admonition-title{background:#1abc9c}.wy-alert.wy-alert-neutral,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.rst-content .wy-alert-neutral.seealso{background:#f3f6f6}.wy-alert.wy-alert-neutral strong,.rst-content .wy-alert-neutral.note strong,.rst-content .wy-alert-neutral.attention strong,.rst-content .wy-alert-neutral.caution strong,.rst-content .wy-alert-neutral.danger strong,.rst-content .wy-alert-neutral.error strong,.rst-content .wy-alert-neutral.hint strong,.rst-content .wy-alert-neutral.important strong,.rst-content .wy-alert-neutral.tip strong,.rst-content .wy-alert-neutral.warning strong,.rst-content .wy-alert-neutral.seealso strong{color:#404040}.wy-alert.wy-alert-neutral a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.rst-content .wy-alert-neutral.seealso a{color:#2980b9}.wy-tray-container{position:fixed;top:-50px;left:0;width:100%;-webkit-transition:top 0.2s ease-in;-moz-transition:top 0.2s ease-in;transition:top 0.2s ease-in}.wy-tray-container.on{top:0}.wy-tray-container li{display:none;width:100%;background:#343131;padding:12px 24px;color:#fff;margin-bottom:6px;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1),0px -1px 2px -1px rgba(255,255,255,0.5) inset}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.btn{display:inline-block;*display:inline;zoom:1;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-size:100%;padding:6px 12px;color:#fff;border:1px solid rgba(0,0,0,0.1);border-bottom:solid 3px rgba(0,0,0,0.1);background-color:#27ae60;text-decoration:none;font-weight:500;box-shadow:0px 1px 2px -1px rgba(255,255,255,0.5) inset;-webkit-transition:all 0.1s linear;-moz-transition:all 0.1s linear;transition:all 0.1s linear;outline-none:false}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;color:#fff;outline:0}.btn:active{border-top:solid 3px rgba(0,0,0,0.1);border-bottom:solid 1px rgba(0,0,0,0.1);box-shadow:0px 1px 2px -1px rgba(0,0,0,0.5) inset}.btn[disabled]{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn:visited{color:#fff}.btn-disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled:hover,.btn-disabled:focus,.btn-disabled:active{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9 !important}.btn-info:hover{background-color:#2e8ece !important}.btn-neutral{background-color:#f3f6f6 !important;color:#404040 !important}.btn-neutral:hover{background-color:#e5ebeb !important;color:#404040}.btn-neutral:visited{color:#404040 !important}.btn-success{background-color:#27ae60 !important}.btn-success:hover{background-color:#295 !important}.btn-danger{background-color:#e74c3c !important}.btn-danger:hover{background-color:#ea6153 !important}.btn-warning{background-color:#e67e22 !important}.btn-warning:hover{background-color:#e98b39 !important}.btn-invert{background-color:#343131}.btn-invert:hover{background-color:#413d3d !important}.btn-link{background-color:transparent !important;color:#2980b9;border-color:transparent;box-shadow:none}.btn-link:hover{background-color:transparent !important;color:#409ad5;border-color:transparent;box-shadow:none}.btn-link:active{background-color:transparent !important;border-color:transparent;border-top:solid 1px transparent;border-bottom:solid 3px transparent;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:before,.wy-btn-group:after{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-menu{position:absolute;top:100%;left:0;display:none;float:left;min-width:100%;background:#fcfcfc;z-index:100;border:solid 1px #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,0.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:solid 1px #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type="search"]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned input,.wy-form-aligned textarea,.wy-form-aligned select,.wy-form-aligned .wy-help-inline,.wy-form-aligned label{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:0.5em 1em 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:0.5em}fieldset{border:0;margin:0;padding:0}legend{display:block;width:100%;border:0;padding:0;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label{display:block;margin:0 0 0.3125em 0;color:#999;font-size:90%}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button{-webkit-appearance:button;cursor:pointer;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}input[type="datetime-local"]{padding:0.34375em 0.625em}input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;margin-right:0.3125em;*height:13px;*width:13px}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input[type="text"]:focus,input[type="password"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus{outline:0;outline:thin dotted \9;border-color:#333}input.no-focus:focus{border-color:#ccc !important}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type="text"][disabled],input[type="password"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="color"][disabled]{cursor:not-allowed;background-color:#f3f6f6;color:#cad2d3}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e74c3c}input[type="file"]:focus:invalid:focus,input[type="radio"]:focus:invalid:focus,input[type="checkbox"]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%}select,textarea{padding:0.5em 0.625em;display:inline-block;border:1px solid #ccc;font-size:0.8em;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#fff;color:#cad2d3;border-color:transparent}.wy-checkbox,.wy-radio{margin:0.5em 0;color:#404040;display:block}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{padding:6px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:solid 1px #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:0.5em 0.625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.wy-control-group{margin-bottom:24px;*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type="text"],.wy-control-group.wy-control-group-error input[type="password"],.wy-control-group.wy-control-group-error input[type="email"],.wy-control-group.wy-control-group-error input[type="url"],.wy-control-group.wy-control-group-error input[type="date"],.wy-control-group.wy-control-group-error input[type="month"],.wy-control-group.wy-control-group-error input[type="time"],.wy-control-group.wy-control-group-error input[type="datetime"],.wy-control-group.wy-control-group-error input[type="datetime-local"],.wy-control-group.wy-control-group-error input[type="week"],.wy-control-group.wy-control-group-error input[type="number"],.wy-control-group.wy-control-group-error input[type="search"],.wy-control-group.wy-control-group-error input[type="tel"],.wy-control-group.wy-control-group-error input[type="color"]{border:solid 2px #e74c3c}.wy-control-group.wy-control-group-error textarea{border:solid 2px #e74c3c}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full input[type="text"],.wy-control-group .wy-form-full input[type="password"],.wy-control-group .wy-form-full input[type="email"],.wy-control-group .wy-form-full input[type="url"],.wy-control-group .wy-form-full input[type="date"],.wy-control-group .wy-form-full input[type="month"],.wy-control-group .wy-form-full input[type="time"],.wy-control-group .wy-form-full input[type="datetime"],.wy-control-group .wy-form-full input[type="datetime-local"],.wy-control-group .wy-form-full input[type="week"],.wy-control-group .wy-form-full input[type="number"],.wy-control-group .wy-form-full input[type="search"],.wy-control-group .wy-form-full input[type="tel"],.wy-control-group .wy-form-full input[type="color"],.wy-control-group .wy-form-halves input[type="text"],.wy-control-group .wy-form-halves input[type="password"],.wy-control-group .wy-form-halves input[type="email"],.wy-control-group .wy-form-halves input[type="url"],.wy-control-group .wy-form-halves input[type="date"],.wy-control-group .wy-form-halves input[type="month"],.wy-control-group .wy-form-halves input[type="time"],.wy-control-group .wy-form-halves input[type="datetime"],.wy-control-group .wy-form-halves input[type="datetime-local"],.wy-control-group .wy-form-halves input[type="week"],.wy-control-group .wy-form-halves input[type="number"],.wy-control-group .wy-form-halves input[type="search"],.wy-control-group .wy-form-halves input[type="tel"],.wy-control-group .wy-form-halves input[type="color"],.wy-control-group .wy-form-thirds input[type="text"],.wy-control-group .wy-form-thirds input[type="password"],.wy-control-group .wy-form-thirds input[type="email"],.wy-control-group .wy-form-thirds input[type="url"],.wy-control-group .wy-form-thirds input[type="date"],.wy-control-group .wy-form-thirds input[type="month"],.wy-control-group .wy-form-thirds input[type="time"],.wy-control-group .wy-form-thirds input[type="datetime"],.wy-control-group .wy-form-thirds input[type="datetime-local"],.wy-control-group .wy-form-thirds input[type="week"],.wy-control-group .wy-form-thirds input[type="number"],.wy-control-group .wy-form-thirds input[type="search"],.wy-control-group .wy-form-thirds input[type="tel"],.wy-control-group .wy-form-thirds input[type="color"]{width:100%}.wy-control-group .wy-form-full{display:block;float:left;margin-right:2.35765%;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{display:block;float:left;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child{margin-right:0}.wy-control-group .wy-form-halves:nth-child(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-child(2n+1){clear:left}.wy-control-group .wy-form-thirds{display:block;float:left;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child{margin-right:0}.wy-control-group .wy-form-thirds:nth-child(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-child(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control{margin:0.5em 0 0 0;font-size:90%}.wy-control-group.fluid-input input[type="text"],.wy-control-group.fluid-input input[type="password"],.wy-control-group.fluid-input input[type="email"],.wy-control-group.fluid-input input[type="url"],.wy-control-group.fluid-input input[type="date"],.wy-control-group.fluid-input input[type="month"],.wy-control-group.fluid-input input[type="time"],.wy-control-group.fluid-input input[type="datetime"],.wy-control-group.fluid-input input[type="datetime-local"],.wy-control-group.fluid-input input[type="week"],.wy-control-group.fluid-input input[type="number"],.wy-control-group.fluid-input input[type="search"],.wy-control-group.fluid-input input[type="tel"],.wy-control-group.fluid-input input[type="color"]{width:100%}.wy-form-message-inline{display:inline-block;padding-left:0.3em;color:#666;vertical-align:middle;font-size:90%}.wy-form-message{display:block;color:#ccc;font-size:70%;margin-top:0.3125em;font-style:italic}.wy-tag-input-group{padding:4px 4px 0px 4px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;background:#fff;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}.wy-tag-input-group .wy-tag{display:inline-block;background-color:rgba(0,0,0,0.1);padding:0.5em 0.625em;border-radius:2px;position:relative;margin-bottom:4px}.wy-tag-input-group .wy-tag .wy-tag-remove{color:#ccc;margin-left:5px}.wy-tag-input-group .wy-tag .wy-tag-remove:hover{color:#e74c3c}.wy-tag-input-group label{margin-left:5px;display:inline-block;margin-bottom:0}.wy-tag-input-group input{border:none;font-size:100%;margin-bottom:4px;box-shadow:none}.wy-form-upload{border:solid 1px #ccc;border-bottom:solid 3px #ccc;background-color:#f3f6f6;padding:24px;display:inline-block;text-align:center;cursor:pointer;color:#404040;-webkit-transition:border-color 0.1s ease-in;-moz-transition:border-color 0.1s ease-in;transition:border-color 0.1s ease-in;*zoom:1}.wy-form-upload:before,.wy-form-upload:after{display:table;content:""}.wy-form-upload:after{clear:both}@media screen and (max-width: 480px){.wy-form-upload{width:100%}}.wy-form-upload .image-drop{display:none}.wy-form-upload .image-desktop{display:none}.wy-form-upload .image-loading{display:none}.wy-form-upload .wy-form-upload-icon{display:block;font-size:32px;color:#b3b3b3}.wy-form-upload .image-drop .wy-form-upload-icon{color:#27ae60}.wy-form-upload p{font-size:90%}.wy-form-upload .wy-form-upload-image{float:left;margin-right:24px}@media screen and (max-width: 480px){.wy-form-upload .wy-form-upload-image{width:100%;margin-bottom:24px}}.wy-form-upload img{max-width:125px;max-height:125px;opacity:0.9;-webkit-transition:opacity 0.1s ease-in;-moz-transition:opacity 0.1s ease-in;transition:opacity 0.1s ease-in}.wy-form-upload .wy-form-upload-content{float:left}@media screen and (max-width: 480px){.wy-form-upload .wy-form-upload-content{width:100%}}.wy-form-upload:hover{border-color:#b3b3b3;color:#404040}.wy-form-upload:hover .image-desktop{display:block}.wy-form-upload:hover .image-drag{display:none}.wy-form-upload:hover img{opacity:1}.wy-form-upload:active{border-top:solid 3px #ccc;border-bottom:solid 1px #ccc}.wy-form-upload.wy-form-upload-big{width:100%;text-align:center;padding:72px}.wy-form-upload.wy-form-upload-big .wy-form-upload-content{float:none}.wy-form-upload.wy-form-upload-file p{margin-bottom:0}.wy-form-upload.wy-form-upload-file .wy-form-upload-icon{display:inline-block;font-size:inherit}.wy-form-upload.wy-form-upload-drop{background-color:#ddf7e8}.wy-form-upload.wy-form-upload-drop .image-drop{display:block}.wy-form-upload.wy-form-upload-drop .image-desktop{display:none}.wy-form-upload.wy-form-upload-drop .image-drag{display:none}.wy-form-upload.wy-form-upload-loading .image-drag{display:none}.wy-form-upload.wy-form-upload-loading .image-desktop{display:none}.wy-form-upload.wy-form-upload-loading .image-loading{display:block}.wy-form-upload.wy-form-upload-loading .wy-input-prefix{display:none}.wy-form-upload.wy-form-upload-loading p{margin-bottom:0}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}.wy-form-gallery-manage{margin-left:-12px;margin-right:-12px}.wy-form-gallery-manage li{float:left;padding:12px;width:20%;cursor:pointer}@media screen and (max-width: 768px){.wy-form-gallery-manage li{width:25%}}@media screen and (max-width: 480px){.wy-form-gallery-manage li{width:50%}}.wy-form-gallery-manage li:active{cursor:move}.wy-form-gallery-manage li>a{padding:12px;background-color:#fff;border:solid 1px #e1e4e5;border-bottom:solid 3px #e1e4e5;display:inline-block;-webkit-transition:all 0.1s ease-in;-moz-transition:all 0.1s ease-in;transition:all 0.1s ease-in}.wy-form-gallery-manage li>a:active{border:solid 1px #ccc;border-top:solid 3px #ccc}.wy-form-gallery-manage img{width:100%;-webkit-transition:all 0.05s ease-in;-moz-transition:all 0.05s ease-in;transition:all 0.05s ease-in}li.wy-form-gallery-edit{position:relative;color:#fff;padding:24px;width:100%;display:block;background-color:#343131;border-radius:4px}li.wy-form-gallery-edit .arrow{position:absolute;display:block;top:-50px;left:50%;margin-left:-25px;z-index:500;height:0;width:0;border-color:transparent;border-style:solid;border-width:25px;border-bottom-color:#343131}@media only screen and (max-width: 480px){.wy-form button[type="submit"]{margin:0.7em 0 0}.wy-form input[type="text"],.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0.3em;display:block}.wy-form label{margin-bottom:0.3em;display:block}.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:0.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-controls{margin:1.5em 0 0 0}.wy-form .wy-help-inline,.wy-form-message-inline,.wy-form-message{display:block;font-size:80%;padding:0.2em 0 0.8em}}@media screen and (max-width: 768px){.tablet-hide{display:none}}@media screen and (max-width: 480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.wy-grid-one-col{*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;max-width:1066px;margin-top:1.618em}.wy-grid-one-col:before,.wy-grid-one-col:after{display:table;content:""}.wy-grid-one-col:after{clear:both}.wy-grid-one-col section{display:block;float:left;margin-right:2.35765%;width:100%;background:#fcfcfc;padding:1.618em;margin-right:0}.wy-grid-one-col section:last-child{margin-right:0}.wy-grid-index-card{*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;max-width:460px;margin-top:1.618em;background:#fcfcfc;padding:1.618em}.wy-grid-index-card:before,.wy-grid-index-card:after{display:table;content:""}.wy-grid-index-card:after{clear:both}.wy-grid-index-card header,.wy-grid-index-card section,.wy-grid-index-card aside{display:block;float:left;margin-right:2.35765%;width:100%}.wy-grid-index-card header:last-child,.wy-grid-index-card section:last-child,.wy-grid-index-card aside:last-child{margin-right:0}.wy-grid-index-card.twocol{max-width:768px}.wy-grid-index-card.twocol section{display:block;float:left;margin-right:2.35765%;width:48.82117%}.wy-grid-index-card.twocol section:last-child{margin-right:0}.wy-grid-index-card.twocol aside{display:block;float:left;margin-right:2.35765%;width:48.82117%}.wy-grid-index-card.twocol aside:last-child{margin-right:0}.wy-grid-search-filter{*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;margin-bottom:24px}.wy-grid-search-filter:before,.wy-grid-search-filter:after{display:table;content:""}.wy-grid-search-filter:after{clear:both}.wy-grid-search-filter .wy-grid-search-filter-input{display:block;float:left;margin-right:2.35765%;width:74.41059%}.wy-grid-search-filter .wy-grid-search-filter-input:last-child{margin-right:0}.wy-grid-search-filter .wy-grid-search-filter-btn{display:block;float:left;margin-right:2.35765%;width:23.23176%}.wy-grid-search-filter .wy-grid-search-filter-btn:last-child{margin-right:0}.wy-table,.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.wy-table caption,.rst-content table.docutils caption,.rst-content table.field-list caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td,.wy-table th,.rst-content table.docutils th,.rst-content table.field-list th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.wy-table td:first-child,.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.wy-table th:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.wy-table thead,.rst-content table.docutils thead,.rst-content table.field-list thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.wy-table thead th,.rst-content table.docutils thead th,.rst-content table.field-list thead th{font-weight:bold;border-bottom:solid 2px #e1e4e5}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.wy-table td p,.rst-content table.docutils td p,.rst-content table.field-list td p{line-height:18px;margin-bottom:0}.wy-table .wy-table-cell-min,.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min{width:1%;padding-right:0}.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:gray;font-size:90%}.wy-table-tertiary{color:gray;font-size:80%}.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td,.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:#f3f6f6}.wy-table-backed{background-color:#f3f6f6}.wy-table-bordered-all,.rst-content table.docutils{border:1px solid #e1e4e5}.wy-table-bordered-all td,.rst-content table.docutils td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.wy-table-bordered-all tbody>tr:last-child td,.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0 !important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}html{height:100%;overflow-x:hidden}body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#404040;min-height:100%;overflow-x:hidden;background:#edf0f2}a{color:#2980b9;text-decoration:none}a:hover{color:#3091d1}a:visited{color:#9b59b6}.link-danger{color:#e74c3c}.link-danger:hover{color:#d62c1a}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}small{font-size:80%}code,.rst-content tt{white-space:nowrap;max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:0 5px;font-family:"Incosolata","Consolata","Monaco",monospace;color:#e74c3c;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.full-width{width:100%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul{list-style:disc;line-height:24px;margin-bottom:24px}.wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li{list-style:disc;margin-left:24px}.wy-plain-list-disc li ul,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li ul{margin-bottom:0}.wy-plain-list-disc li li,.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li{list-style:circle}.wy-plain-list-disc li li li,.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li{list-style:square}.wy-plain-list-decimal,.rst-content .section ol,.rst-content ol.arabic{list-style:decimal;line-height:24px;margin-bottom:24px}.wy-plain-list-decimal li,.rst-content .section ol li,.rst-content ol.arabic li{list-style:decimal;margin-left:24px}.wy-type-large{font-size:120%}.wy-type-normal{font-size:100%}.wy-type-small{font-size:100%}.wy-type-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980b9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27ae60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#e74c3c !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}.codeblock-example{border:1px solid #e1e4e5;border-bottom:none;padding:24px;padding-top:48px;font-weight:500;background:#fff;position:relative}.codeblock-example:after{content:"Example";position:absolute;top:0px;left:0px;background:#9b59b6;color:#fff;padding:6px 12px}.codeblock-example.prettyprint-example-only{border:1px solid #e1e4e5;margin-bottom:24px}.codeblock,.rst-content .literal-block,div[class^='highlight']{border:1px solid #e1e4e5;padding:0px;overflow-x:auto;background:#fff;margin:1px 0 24px 0}.codeblock div[class^='highlight'],.rst-content .literal-block div[class^='highlight'],div[class^='highlight'] div[class^='highlight']{border:none;background:none;margin:0}div[class^='highlight'] td.code{width:100%}.linenodiv pre{border-right:solid 1px #e6e9ea;margin:0;padding:12px 12px;font-family:"Incosolata","Consolata","Monaco",monospace;font-size:12px;line-height:1.5;color:#d9d9d9}div[class^='highlight'] pre{white-space:pre;margin:0;padding:12px 12px;font-family:"Incosolata","Consolata","Monaco",monospace;font-size:12px;line-height:1.5;display:block;overflow:auto;color:#404040}pre.literal-block{@extends .codeblock;}@media print{.codeblock,.rst-content .literal-block,div[class^='highlight'],div[class^='highlight'] pre{white-space:pre-wrap}}.hll{background-color:#ffc;margin:0 -12px;padding:0 12px;display:block}.c{color:#998;font-style:italic}.err{color:#a61717;background-color:#e3d2d2}.k{font-weight:bold}.o{font-weight:bold}.cm{color:#998;font-style:italic}.cp{color:#999;font-weight:bold}.c1{color:#998;font-style:italic}.cs{color:#999;font-weight:bold;font-style:italic}.gd{color:#000;background-color:#fdd}.gd .x{color:#000;background-color:#faa}.ge{font-style:italic}.gr{color:#a00}.gh{color:#999}.gi{color:#000;background-color:#dfd}.gi .x{color:#000;background-color:#afa}.go{color:#888}.gp{color:#555}.gs{font-weight:bold}.gu{color:purple;font-weight:bold}.gt{color:#a00}.kc{font-weight:bold}.kd{font-weight:bold}.kn{font-weight:bold}.kp{font-weight:bold}.kr{font-weight:bold}.kt{color:#458;font-weight:bold}.m{color:#099}.s{color:#d14}.n{color:#333}.na{color:teal}.nb{color:#0086b3}.nc{color:#458;font-weight:bold}.no{color:teal}.ni{color:purple}.ne{color:#900;font-weight:bold}.nf{color:#900;font-weight:bold}.nn{color:#555}.nt{color:navy}.nv{color:teal}.ow{font-weight:bold}.w{color:#bbb}.mf{color:#099}.mh{color:#099}.mi{color:#099}.mo{color:#099}.sb{color:#d14}.sc{color:#d14}.sd{color:#d14}.s2{color:#d14}.se{color:#d14}.sh{color:#d14}.si{color:#d14}.sx{color:#d14}.sr{color:#009926}.s1{color:#d14}.ss{color:#990073}.bp{color:#999}.vc{color:teal}.vg{color:teal}.vi{color:teal}.il{color:#099}.gc{color:#999;background-color:#eaf2f5}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width: 480px){.wy-breadcrumbs-extra{display:none}.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:before,.wy-menu-horiz:after{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz ul,.wy-menu-horiz li{display:inline-block}.wy-menu-horiz li:hover{background:rgba(255,255,255,0.1)}.wy-menu-horiz li.divide-left{border-left:solid 1px #404040}.wy-menu-horiz li.divide-right{border-right:solid 1px #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical header{height:32px;display:inline-block;line-height:32px;padding:0 1.618em;display:block;font-weight:bold;text-transform:uppercase;font-size:80%;color:#2980b9;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:solid 1px #404040}.wy-menu-vertical li.divide-bottom{border-bottom:solid 1px #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:gray;border-right:solid 1px #c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a{color:#404040;padding:0.4045em 1.618em;font-weight:bold;position:relative;background:#fcfcfc;border:none;border-bottom:solid 1px #c9c9c9;border-top:solid 1px #c9c9c9;padding-left:1.618em -4px}.wy-menu-vertical li.on a:hover,.wy-menu-vertical li.current>a:hover{background:#fcfcfc}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical .local-toc li ul{display:block}.wy-menu-vertical li ul li a{margin-bottom:0;color:#b3b3b3;font-weight:normal}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:0.4045em 1.618em;display:block;position:relative;font-size:90%;color:#b3b3b3}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-side-nav-search{z-index:200;background-color:#2980b9;text-align:center;padding:0.809em;display:block;color:#fcfcfc;margin-bottom:0.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto 0.809em auto;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a{color:#fcfcfc;font-size:100%;font-weight:bold;display:inline-block;padding:4px 6px;margin-bottom:0.809em}.wy-side-nav-search>a:hover,.wy-side-nav-search .wy-dropdown>a:hover{background:rgba(255,255,255,0.1)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all 0.2s ease-in;-moz-transition:all 0.2s ease-in;transition:all 0.2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:left repeat-y #fcfcfc;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC);background-size:300px 1px}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:absolute;top:0;left:0;width:300px;overflow:hidden;min-height:100%;background:#343131;z-index:200}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:0.4045em 0.809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:before,.wy-nav-top:after{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:bold}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,0.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:#999}footer p{margin-bottom:12px}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:before,.rst-footer-buttons:after{display:table;content:""}.rst-footer-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:solid 1px #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:solid 1px #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:gray;font-size:90%}@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width: 1400px){.wy-nav-content-wrap{background:rgba(0,0,0,0.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.wy-nav-side{display:none}.wy-nav-content-wrap{margin-left:0}}nav.stickynav{position:fixed;top:0}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .wy-dropdown .caret,.wy-dropdown .rst-versions .rst-current-version .caret,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-success .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-info .rst-versions .rst-current-version .wy-input-context,.rst-versions .rst-current-version .wy-tag-input-group .wy-tag .wy-tag-remove,.wy-tag-input-group .wy-tag .rst-versions .rst-current-version .wy-tag-remove,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .icon{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}}.rst-content img{max-width:100%;height:auto !important}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img{margin-bottom:24px}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content .note .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .tip .last,.rst-content .warning .last,.rst-content .seealso .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,0.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent !important;border-color:rgba(0,0,0,0.1) !important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .line-block{margin-left:24px}.rst-content .topic-title{font-weight:bold;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0px 0px 24px 24px}.rst-content .align-left{float:left;margin:0px 24px 24px 0px}.rst-content .align-center{margin:auto;display:block}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink{display:none;visibility:hidden;font-size:14px}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after{visibility:visible;content:"\f0c1";font-family:fontawesome-webfont;display:inline-block}.rst-content h1:hover .headerlink,.rst-content h2:hover .headerlink,.rst-content h3:hover .headerlink,.rst-content h4:hover .headerlink,.rst-content h5:hover .headerlink,.rst-content h6:hover .headerlink,.rst-content dl dt:hover .headerlink{display:inline-block}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:solid 1px #e1e4e5}.rst-content .sidebar p,.rst-content .sidebar ul,.rst-content .sidebar dl{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;font-weight:bold;background:#e1e4e5;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;display:inline-block;font-weight:bold;padding:0 6px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:super;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:#999}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent !important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.field-list{border:none}.rst-content table.field-list td{border:none;padding-top:5px}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left;padding-left:0}.rst-content tt{color:#000}.rst-content tt big,.rst-content tt em{font-size:100% !important;line-height:normal}.rst-content tt .xref,a .rst-content tt{font-weight:bold}.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:bold}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px !important}.rst-content dl dd{margin:0 0 12px 24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:inline-block;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:solid 3px #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 3px #ccc;background:#f0f0f0;color:gray}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) tt{font-weight:bold}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname{background-color:transparent;border:none;padding:0;font-size:100% !important}.rst-content dl:not(.docutils) tt.descname{font-weight:bold}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:bold}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-link,.rst-content .viewcode-back{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}@media screen and (max-width: 480px){.rst-content .sidebar{width:100%}}span[id*='MathJax-Span']{color:#404040} diff --git a/apiref.html b/apiref.html index 2598ccf9..559d0f0b 100644 --- a/apiref.html +++ b/apiref.html @@ -8,7 +8,7 @@ - API Reference — nghttp2 0.3.0-DEV documentation + API Reference — nghttp2 0.4.0-DEV documentation @@ -23,7 +23,7 @@ diff --git a/index.html b/index.html index a0d445f3..f0ac8d3e 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,7 @@ - nghttp2 - HTTP/2.0 C Library — nghttp2 0.3.0-DEV documentation + nghttp2 - HTTP/2.0 C Library — nghttp2 0.4.0-DEV documentation @@ -23,7 +23,7 @@ @@ -193,6 +193,7 @@ version 2.0.

Released Versions¶

@@ -211,7 +212,7 @@ version 2.0.

diff --git a/nghttp2.h.html b/nghttp2.h.html index 8300e586..96dbf742 100644 --- a/nghttp2.h.html +++ b/nghttp2.h.html @@ -8,7 +8,7 @@ - nghttp2.h — nghttp2 0.3.0-DEV documentation + nghttp2.h — nghttp2 0.4.0-DEV documentation @@ -23,7 +23,7 @@ @@ -180,7 +180,7 @@ * @macro * Version number of the nghttp2 library release */ -#define NGHTTP2_VERSION "0.3.0-DEV" +#define NGHTTP2_VERSION "0.4.0-DEV" /** * @macro @@ -188,7 +188,7 @@ * release. This is a 24 bit number with 8 bits for major number, 8 bits * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. */ -#define NGHTTP2_VERSION_NUM 0x000300 +#define NGHTTP2_VERSION_NUM 0x000400 #endif /* NGHTTP2VER_H */
@@ -202,7 +202,7 @@ diff --git a/objects.inv b/objects.inv index bd43ceba1307cd0643a546e7690c0ae415f1c7b3..d8b9be9f4de68ed933acb372dca6aa9190a77ae4 100644 GIT binary patch delta 2028 zcmV>1B4bk=;}`GpjDQkcU(;~I(%I)Pv*P{pq5neL*N614 z*(#5ll+8^3uTMLcU0Edl+pp*ztyow_`{{$-|N6(g?tyi}?w(WlO@7d>1_VUU1*AJAq zE;a4%x@8*F^L3x_MPXFtSJsI47frRNMVTLxifP#~W!bGaiB;KAJBDe)Fwa)3s<=5( zn5LUBdaX40ur0#_qgj8>jnCrYJFJyYL^p^_=gw+P=C)uu|EUU}+kDnJCG;N=_wr+9T92a5H+BK==JQL5yS8_Ok(>GVcRBi-*kU$5j>072%C3#_!hp) zZ7eIuz`A7NL1Sf^Ly+?rmDL5rSN`+o)!n@cU)krOh@q=QU$;%xb_irESh)I%pnWEZ z&m@+#HD8+E)4t>qeML?um81y@FJ!nQMphN7|vUT7+AuKyLNfOv- z&!SfWP<@CI*=Oj!j@V3BV{JoFFY&t=NdGq$C7GbWVqt&jORC>2o*^vV=H`~;5d-T2 zZGaQ$R)(-cYU8kZ!*+?_7!?AZ$F=ip+J^Itt(wz2YPQQu1U%m8jgplUG?fyKDFu`~ z-i4$nle|pocLn0nnSUQjY}ht0Szi%%aaO1Y*BAL`J3iGdPT>q>OI^UjoDTV}W1&Ez zqo7DQ=TU#=5yLgn-S4CTAl{~sNNSv90gVT5<}tjG!rihAG?bjvw0Q;hu(j9hCO2w(JvvP_v&2~d>;OE|-J&_c&q`*cl!9`J4l zk(vjt%XL9lMjocab`%^hcPdsMIheAy2V6Bw01SVpZg@HvWC4FrAT)l%J-Q9uuP#}V zWFRnMjbsHZiB}YKwnuYQaiR17rcE;zy}(Dp}P)$Ko!-73;{kT5-EmUN}`mRt+ZjtOjab4=n#K&3osVMR|J2xrJ#5 zx{uR0E$1e-(Fz-0YAe&jqNY#^y1NWkP#jna#0MFz+okw1!9{52txvP&fN?}8NHLWP z1Za2X9PLBaFAXnpig!(rsP&`4A9LNOF8O~axIJ#XNDRCmIiHkU;(B7&$b2Er0&AXp zui|k5Cw8z>m;zvFA5#5*Cf863`C=8|`L5opv{-ns%{g3uJ%bbJDZw>H)Q%@8`C+2+ zZLZsMVj&)M$pQ$tA#79@Sh;p=l=d0J^EOsceiL4Z2ulZ&J#Ub{q#uo^ z;qVq@-SxXWjUEuflxrT4NO}O|wI3Jsj3ZbZxS3jKov1~XYUjD$TiAdSQeakBet~Vb z{4DdxXqrRj(-GanxuV4qAW)8L`Y(U?o){?3Y)&(C)O_srd4yzr&rHyrq{&{h{O$id z&$~R^L=Lmm#;BmeO zO~>|7WjMh~+zpF%qlW2m7aG{&DfVr*23+?M%YnT07im$TAuq7e6cs~L0Kg7K2o)*6 KK=>cE8laM_(B)A8 delta 2012 zcmV<22P62=5Wx_TJpnV3K0<%na+^pHea}~@YWFo%C69R{(#WP3ftE`g=Vc0`kwh5* z;UdTR`t9LnbTOP!_Q@rS5#7_LPoM6YL%NBQjrcVy%FUNJcoOmKtd6A9I@r*1=AENOphwvdlj7G%I-_ zN-arwP?aeU(;lCd{+tCFL34B|>4&laL6 zq&r~{$4^1{Txj%Rn+Jaf!IM-vpKSW?P%rP9zF-cY+pG16kKGEFd7fe2x!p2P|7tSs z8b6Q?B4hU=*ob^+WciwjQJ2dyN_GVoNtwUC|9oelVR_84bW{3fJAg-P$Ka;@z+4aW zpxN$RghwSWt^|&-81QgkCC?W>H;IJW3T?kZqC7VZW_c80%VK|X&#Y5HWEvPsFcMa%7o?X-w<3RZ=rF z=yD6(uckf!=N5k#rcpz5oKQGWV0gC8SGx5`7A{SLzUX%v2#WlHwPSlW@a#(eeiP>w z)zcv=FHk?S@7>CVstc-Q0lFK$<@)Qj?Rad#zcI%pu2I1zvue-QzIzXNcJ2~N!Er>T zgn;<+8N=T~_jJIVj>T@u;hQ8z`*+hNWdv1&rK#U>eKdc4`oJ{C%}v{73lPr>wxmB4 zf4Oa(eK$ty>IDP{=3p{B7}mmmK+~WFGciFac4-cjv!=ohHyok4lgg(o3ZBF^%|#0( zSk0YToJVOMm9GjaqS+fX$qB2D*I~o5J+7NlKcN6w(!)}Vc#dsC6yE4Ru$IbHkRiY* zZudLNc$9x^V?qVr2!(>QBy=O@chQhxf$VSSy4PHQ6P>@4!r1T((!~QAh^5fbZOdM< z6wZ{l>5iDAu%FNb{zy*JCTvDKZ_1 zy}nX8q>MI9-(d=>awkfjR^?M#kpVv|Q4wcHzXe7jweIUg5@~p_8LN9n+N@(l$kZrZ z)LidK;AYs>?=R9S4`mO0`t}I|x}WP_t?jtO+_i1F?A9hEB1sxYn|E4qAQy%s1+D)W z!RUW}uzhoZHX$cERck*2rPpKA=9#PvOFWc>6rGqtpk=? zNs+S`VhY_iRT|Pa4#QH-VN0q+oz}*?_c-Wl5{L~cYYfZRz46B9a$=&^H0aKqzoNWF z6_*@Z)FGLyPv=_=Yoew#b#Kb(8xr^mDLj9PU6c%TK2D0V7*p-meIn#m*0wPA*NgGK z>{|b#Myx07=&*l%1~p7|7ssrH!p2LnJB>5P^`;Z$!it*Ksidt8m!Zy1Ti!k1RY}WV zDZ~Pmo?t5|2b2&QT&#*kvMcv0z@`W5vW5|SEry8^>!nF`z&pRb&6s93DW0)@E!lr4 z48{k=37F_6@3h9ZOy3p7!x>64gsYuBHLhgiZNix}v;XU4}oo}2i zB}XVd$CdfS`j*15c+tzMJH6SXBY~{8H2czpis%U{*2)U$J*m3 zu<%a<>3q_lFm!E{4wy-jQ&dluChka_xG-0MRr3n0$v%>lIREzlRN!fU=xy7V&L4> z9?mp37nH<;*ly)5reho58gzY2fdHpfYNE)}qyWd0@7)rHhEAFVKdXM4s-g;vMRWN1jii~pwt(Fp8@cl}+5FX8 z4<9l0vl)2oIdZ*cB4X`kV%NTUlw&ia^XpuhAdPege#z^dVU_1nXf=OkL;P`4v#~N) z8@e!D8D&I0)%7IU3AL#{I_02Bl&xaPNJOKY+K5;qguD^6Bw7u(|COM)3Z5FAu2>7A1IZ u=Aw9V^lf8FbDO^HF3^J(w55Kkq782b!F_x}1wB1v0VU>i7ylp2NT8BVdgMR= diff --git a/package_README.html b/package_README.html index e7b5bab1..c1c3cb09 100644 --- a/package_README.html +++ b/package_README.html @@ -8,7 +8,7 @@ - nghttp2 - HTTP/2.0 C Library — nghttp2 0.3.0-DEV documentation + nghttp2 - HTTP/2.0 C Library — nghttp2 0.4.0-DEV documentation @@ -23,7 +23,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+ +
+

API Reference¶

+
+

Includes¶

+

To use the public APIs, include nghttp2/nghttp2.h:

+
#include <nghttp2/nghttp2.h>
+
+
+

The header files are also available online: nghttp2.h and +nghttp2ver.h.

+
+
+

Remarks¶

+

Do not call nghttp2_session_send(), nghttp2_session_recv() or +nghttp2_session_mem_recv() from the nghttp2 callback functions +directly or indirectly. It will lead to the crash. You can submit +requests or frames in the callbacks then call nghttp2_session_send(), +nghttp2_session_recv() or nghttp2_session_mem_recv() outside of the +callbacks.

+
+
+

Macros¶

+
+
+NGHTTP2_VERSION¶
+

Version number of the nghttp2 library release

+
+ +
+
+NGHTTP2_VERSION_NUM¶
+

Numerical representation of the version number of the nghttp2 library +release. This is a 24 bit number with 8 bits for major number, 8 bits +for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.

+
+ +
+
+NGHTTP2_PROTO_VERSION_ID¶
+

The protocol version identification of this library supports.

+
+ +
+
+NGHTTP2_PROTO_VERSION_ID_LEN¶
+

The length of NGHTTP2_PROTO_VERSION_ID.

+
+ +
+
+NGHTTP2_VERSION_AGE¶
+

The age of nghttp2_info

+
+ +
+
+NGHTTP2_PRI_DEFAULT¶
+

The default priority value

+
+ +
+
+NGHTTP2_PRI_LOWEST¶
+

The lowest priority value

+
+ +
+
+NGHTTP2_MAX_WINDOW_SIZE¶
+

The maximum window size

+
+ +
+
+NGHTTP2_INITIAL_WINDOW_SIZE¶
+

The initial window size for stream level flow control.

+
+ +
+
+NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE¶
+

The initial window size for connection level flow control.

+
+ +
+
+NGHTTP2_MAX_HEADER_TABLE_SIZE¶
+

The maximum header table size.

+
+ +
+
+NGHTTP2_CLIENT_CONNECTION_HEADER¶
+

The client connection header.

+
+ +
+
+NGHTTP2_CLIENT_CONNECTION_HEADER_LEN¶
+

The length of NGHTTP2_CLIENT_CONNECTION_HEADER.

+
+ +
+
+NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS¶
+

Default maximum concurrent streams.

+
+ +
+
+

Enums¶

+
+
+nghttp2_error¶
+

Error codes used in this library. The code range is [-999, -500], +inclusive. The following values are defined:

+
+
+NGHTTP2_ERR_INVALID_ARGUMENT¶
+

(-501) +Invalid argument passed.

+
+ +
+
+NGHTTP2_ERR_UNSUPPORTED_VERSION¶
+

(-503) +The specified protocol version is not supported.

+
+ +
+
+NGHTTP2_ERR_WOULDBLOCK¶
+

(-504) +Used as a return value from nghttp2_send_callback and +nghttp2_recv_callback to indicate that the operation +would block.

+
+ +
+
+NGHTTP2_ERR_PROTO¶
+

(-505) +General protocol error

+
+ +
+
+NGHTTP2_ERR_INVALID_FRAME¶
+

(-506) +The frame is invalid.

+
+ +
+
+NGHTTP2_ERR_EOF¶
+

(-507) +The peer performed a shutdown on the connection.

+
+ +
+
+NGHTTP2_ERR_DEFERRED¶
+

(-508) +Used as a return value from +nghttp2_data_source_read_callback() to indicate that data +transfer is postponed. See +nghttp2_data_source_read_callback() for details.

+
+ +
+
+NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE¶
+

(-509) +Stream ID has reached the maximum value. Therefore no stream ID +is available.

+
+ +
+
+NGHTTP2_ERR_STREAM_CLOSED¶
+

(-510) +The stream is already closed; or the stream ID is invalid.

+
+ +
+
+NGHTTP2_ERR_STREAM_CLOSING¶
+

(-511) +RST_STREAM has been added to the outbound queue. The stream is in +closing state.

+
+ +
+
+NGHTTP2_ERR_STREAM_SHUT_WR¶
+

(-512) +The transmission is not allowed for this stream (e.g., a frame +with END_STREAM flag set has already sent).

+
+ +
+
+NGHTTP2_ERR_INVALID_STREAM_ID¶
+

(-513) +The stream ID is invalid.

+
+ +
+
+NGHTTP2_ERR_INVALID_STREAM_STATE¶
+

(-514) +The state of the stream is not valid (e.g., DATA cannot be sent +to the stream if response HEADERS has not been sent).

+
+ +
+
+NGHTTP2_ERR_DEFERRED_DATA_EXIST¶
+

(-515) +Another DATA frame has already been deferred.

+
+ +
+
+NGHTTP2_ERR_START_STREAM_NOT_ALLOWED¶
+

(-516) +Starting new stream is not allowed. (e.g., GOAWAY has been sent +and/or received.

+
+ +
+
+NGHTTP2_ERR_GOAWAY_ALREADY_SENT¶
+

(-517) +GOAWAY has already been sent.

+
+ +
+
+NGHTTP2_ERR_INVALID_HEADER_BLOCK¶
+

(-518) +The received frame contains the invalid header block. (e.g., +There are duplicate header names; or the header names are not +encoded in US-ASCII character set and not lower cased; or the +header name is zero-length string; or the header value contains +multiple in-sequence NUL bytes).

+
+ +
+
+NGHTTP2_ERR_INVALID_STATE¶
+

(-519) +Indicates that the context is not suitable to perform the +requested operation.

+
+ +
+
+NGHTTP2_ERR_GZIP¶
+

(-520) +The gzip error.

+
+ +
+
+NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE¶
+

(-521) +The user callback function failed due to the temporal error.

+
+ +
+
+NGHTTP2_ERR_FRAME_SIZE_ERROR¶
+

(-522) +The length of the frame is invalid, either too large or too small.

+
+ +
+
+NGHTTP2_ERR_HEADER_COMP¶
+

(-523) +Header block inflate/deflate error.

+
+ +
+
+NGHTTP2_ERR_FLOW_CONTROL¶
+

(-524) +Flow control error

+
+ +
+
+NGHTTP2_ERR_INSUFF_BUFSIZE¶
+

(-525) +Insufficient buffer size given to function.

+
+ +
+
+NGHTTP2_ERR_PAUSE¶
+

(-526) +Callback was paused by the application

+
+ +
+
+NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS¶
+

(-527) +There are too many in-flight SETTING frame and no more +transmission of SETTINGS is allowed.

+
+ +
+
+NGHTTP2_ERR_PUSH_DISABLED¶
+

(-528) +The server push is disabled.

+
+ +
+
+NGHTTP2_ERR_FATAL¶
+

(-900) +The errors < NGHTTP2_ERR_FATAL mean that the library is +under unexpected condition and cannot process any further data +reliably (e.g., out of memory).

+
+ +
+
+NGHTTP2_ERR_NOMEM¶
+

(-901) +Out of memory. This is a fatal error.

+
+ +
+
+NGHTTP2_ERR_CALLBACK_FAILURE¶
+

(-902) +The user callback function failed. This is a fatal error.

+
+ +
+ +
+
+nghttp2_frame_type¶
+

The control frame types in HTTP/2.0.

+
+
+NGHTTP2_DATA¶
+

(0) +The DATA frame.

+
+ +
+
+NGHTTP2_HEADERS¶
+

(1) +The HEADERS frame.

+
+ +
+
+NGHTTP2_PRIORITY¶
+

(2) +The PRIORITY frame.

+
+ +
+
+NGHTTP2_RST_STREAM¶
+

(3) +The RST_STREAM frame.

+
+ +
+
+NGHTTP2_SETTINGS¶
+

(4) +The SETTINGS frame.

+
+ +
+
+NGHTTP2_PUSH_PROMISE¶
+

(5) +The PUSH_PROMISE frame.

+
+ +
+
+NGHTTP2_PING¶
+

(6) +The PING frame.

+
+ +
+
+NGHTTP2_GOAWAY¶
+

(7) +The GOAWAY frame.

+
+ +
+
+NGHTTP2_WINDOW_UPDATE¶
+

(9) +The WINDOW_UPDATE frame.

+
+ +
+
+NGHTTP2_CONTINUATION¶
+

(10) +The CONTINUATION frame.

+
+ +
+ +
+
+nghttp2_flag¶
+

The flags for HTTP/2.0 frames. This enum defines all flags for +frames, assuming that the same flag name has the same mask.

+
+
+NGHTTP2_FLAG_NONE¶
+

(0) +No flag set.

+
+ +
+
+NGHTTP2_FLAG_END_STREAM¶
+

(0x1) +The END_STREAM flag.

+
+ +
+
+NGHTTP2_FLAG_END_HEADERS¶
+

(0x4) +The END_HEADERS flag.

+
+ +
+
+NGHTTP2_FLAG_PRIORITY¶
+

(0x8) +The PRIORITY flag.

+
+ +
+
+NGHTTP2_FLAG_END_PUSH_PROMISE¶
+

(0x4) +The END_PUSH_PROMISE flag.

+
+ +
+
+NGHTTP2_FLAG_ACK¶
+

(0x1) +The ACK flag.

+
+ +
+ +
+
+nghttp2_settings_id¶
+

The SETTINGS ID.

+
+
+NGHTTP2_SETTINGS_HEADER_TABLE_SIZE¶
+

(1) +SETTINGS_HEADER_TABLE_SIZE

+
+ +
+
+NGHTTP2_SETTINGS_ENABLE_PUSH¶
+

(2) +SETTINGS_ENABLE_PUSH

+
+ +
+
+NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS¶
+

(4) +SETTINGS_MAX_CONCURRENT_STREAMS

+
+ +
+
+NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE¶
+

(7) +SETTINGS_INITIAL_WINDOW_SIZE

+
+ +
+
+NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS¶
+

(10) +SETTINGS_FLOW_CONTROL_OPTIONS

+
+ +
+
+NGHTTP2_SETTINGS_MAX¶
+

(10) +Maximum ID of nghttp2_settings_id.

+
+ +
+ +
+
+nghttp2_error_code¶
+

The status codes for the RST_STREAM and GOAWAY frames.

+
+
+NGHTTP2_NO_ERROR¶
+

(0) +No errors.

+
+ +
+
+NGHTTP2_PROTOCOL_ERROR¶
+

(1) +PROTOCOL_ERROR

+
+ +
+
+NGHTTP2_INTERNAL_ERROR¶
+

(2) +INTERNAL_ERROR

+
+ +
+
+NGHTTP2_FLOW_CONTROL_ERROR¶
+

(3) +FLOW_CONTROL_ERROR

+
+ +
+
+NGHTTP2_SETTINGS_TIMEOUT¶
+

(4) +SETTINGS_TIMEOUT

+
+ +
+
+NGHTTP2_STREAM_CLOSED¶
+

(5) +STREAM_CLOSED

+
+ +
+
+NGHTTP2_FRAME_SIZE_ERROR¶
+

(6) +FRAME_SIZE_ERROR

+
+ +
+
+NGHTTP2_REFUSED_STREAM¶
+

(7) +REFUSED_STREAM

+
+ +
+
+NGHTTP2_CANCEL¶
+

(8) +CANCEL

+
+ +
+
+NGHTTP2_COMPRESSION_ERROR¶
+

(9) +COMPRESSION_ERROR

+
+ +
+
+NGHTTP2_CONNECT_ERROR¶
+

(10) +CONNECT_ERROR

+
+ +
+
+NGHTTP2_ENHANCE_YOUR_CALM¶
+

(420) +ENHANCE_YOUR_CALM

+
+ +
+ +
+
+nghttp2_headers_category¶
+

The category of HEADERS, which indicates the role of the frame. In +HTTP/2.0 spec, request, response, push response and other arbitrary +headers (e.g., trailers) are all called just HEADERS. To give the +application the role of incoming HEADERS frame, we define several +categories.

+
+
+NGHTTP2_HCAT_REQUEST¶
+

(0) +The HEADERS frame is opening new stream, which is analogous to +SYN_STREAM in SPDY.

+
+ +
+
+NGHTTP2_HCAT_RESPONSE¶
+

(1) +The HEADERS frame is the first response headers, which is +analogous to SYN_REPLY in SPDY.

+
+ +
+
+NGHTTP2_HCAT_PUSH_RESPONSE¶
+

(2) +The HEADERS frame is the first headers sent against reserved +stream.

+
+ +
+
+NGHTTP2_HCAT_HEADERS¶
+

(3) +The HEADERS frame which does not apply for the above categories, +which is analogous to HEADERS in SPDY.

+
+ +
+ +
+
+nghttp2_opt¶
+

Configuration options for nghttp2_session.

+
+
+NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE¶
+

(1) +This option prevents the library from sending WINDOW_UPDATE for a +stream automatically. If this option is set to nonzero, the +library won’t send WINDOW_UPDATE for a stream and the application +is responsible for sending WINDOW_UPDATE using +nghttp2_submit_window_update(). By default, this option is set to +zero.

+
+ +
+
+NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE¶
+

(1 << 1) +This option prevents the library from sending WINDOW_UPDATE for a +connection automatically. If this option is set to nonzero, the +library won’t send WINDOW_UPDATE for a connection and the +application is responsible for sending WINDOW_UPDATE with stream +ID 0 using nghttp2_submit_window_update(). By default, this +option is set to zero.

+
+ +
+
+NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS¶
+

(1 << 2) +This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of +remote endpoint as if it is received in SETTINGS frame. Without +specifying this option, before the local endpoint receives +SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote +endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may +cause problem if local endpoint submits lots of requests +initially and sending them at once to the remote peer may lead to +the rejection of some requests. Specifying this option to the +sensible value, say 100, may avoid this kind of issue. This value +will be overwritten if the local endpoint receives +SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.

+
+ +
+ +
+
+

Types (structs, unions and typedefs)¶

+
+
+nghttp2_session¶
+

The primary structure to hold the resources needed for a HTTP/2.0 +session. The details of this structure are intentionally hidden +from the public API.

+
+ +
+
+nghttp2_info¶
+

This struct is what nghttp2_version() returns. It holds +information about the particular nghttp2 version.

+
+
+int age¶
+

Age of this struct. This instance of nghttp2 sets it to +NGHTTP2_VERSION_AGE but a future version may bump it and +add more struct fields at the bottom

+
+ +
+
+int version_num¶
+

the NGHTTP2_VERSION_NUM number (since age ==1)

+
+ +
+
+const char *version_str¶
+

points to the NGHTTP2_VERSION string (since age ==1)

+
+ +
+
+const char *proto_str¶
+

points to the NGHTTP2_PROTO_VERSION_ID string this +instance implements (since age ==1)

+
+ +
+ +
+
+nghttp2_nv¶
+

The name/value pair, which mainly used to represent header fields.

+
+
+uint8_t *name¶
+

The name byte string, which is not necessarily NULL +terminated.

+
+ +
+
+uint8_t *value¶
+

The value byte string, which is not necessarily NULL +terminated.

+
+ +
+
+uint16_t namelen¶
+

The length of the name.

+
+ +
+
+uint16_t valuelen¶
+

The length of the value.

+
+ +
+ +
+
+nghttp2_frame_hd¶
+

The frame header.

+
+
+size_t length¶
+

The length field of this frame, excluding frame header.

+
+ +
+
+int32_t stream_id¶
+

The stream identifier (aka, stream ID)

+
+ +
+
+uint8_t type¶
+

The type of this frame. See nghttp2_frame().

+
+ +
+
+uint8_t flags¶
+

The flags.

+
+ +
+ +
+
+nghttp2_data_source¶
+

This union represents the some kind of data source passed to +nghttp2_data_source_read_callback.

+
+
+int fd¶
+

The integer field, suitable for a file descriptor.

+
+ +
+
+void *ptr¶
+

The pointer to an arbitrary object.

+
+ +
+ +
+
+typedef ssize_t (*nghttp2_data_source_read_callback)(nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, int *eof, nghttp2_data_source *source, void *user_data)¶
+

Callback function invoked when the library wants to read data from +the source. The read data is sent in the stream stream_id. The +implementation of this function must read at most length bytes of +data from source (or possibly other places) and store them in +buf and return number of data stored in buf. If EOF is reached, +set *eof to 1. If the application wants to postpone DATA frames, +(e.g., asynchronous I/O, or reading data blocks for long time), it +is achieved by returning NGHTTP2_ERR_DEFERRED without +reading any data in this invocation. The library removes DATA +frame from the outgoing queue temporarily. To move back deferred +DATA frame to outgoing queue, call nghttp2_session_resume_data(). +In case of error, there are 2 choices. Returning +NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE will close the stream +by issuing RST_STREAM with NGHTTP2_INTERNAL_ERROR. +Returning NGHTTP2_ERR_CALLBACK_FAILURE will signal the +entire session failure.

+
+ +
+
+nghttp2_data_provider¶
+

This struct represents the data source and the way to read a chunk +of data from it.

+
+
+nghttp2_data_source source¶
+

The data source.

+
+ +
+
+nghttp2_data_source_read_callback read_callback¶
+

The callback function to read a chunk of data from the source.

+
+ +
+ +
+
+nghttp2_data¶
+

The DATA frame. The received data is delivered via +nghttp2_on_data_chunk_recv_callback.

+
+ +
+
+nghttp2_headers¶
+

The HEADERS frame. It has the following members:

+
+
+nghttp2_frame_hd hd¶
+

The frame header.

+
+ +
+
+nghttp2_nv *nva¶
+

The name/value pairs.

+
+ +
+
+size_t nvlen¶
+

The number of name/value pairs in nva.

+
+ +
+
+nghttp2_headers_category cat¶
+

The category of this HEADERS frame.

+
+ +
+
+int32_t pri¶
+

The priority.

+
+ +
+ +
+
+nghttp2_priority¶
+

The PRIORITY frame. It has the following members:

+
+
+nghttp2_frame_hd hd¶
+

The frame header.

+
+ +
+
+int32_t pri¶
+

The priority.

+
+ +
+ +
+
+nghttp2_rst_stream¶
+

The RST_STREAM frame. It has the following members:

+
+
+nghttp2_frame_hd hd¶
+

The frame header.

+
+ +
+
+nghttp2_error_code error_code¶
+

The error code. See nghttp2_error_code.

+
+ +
+ +
+
+nghttp2_settings_entry¶
+

The SETTINGS ID/Value pair. It has the following members:

+
+
+int32_t settings_id¶
+

The SETTINGS ID. See nghttp2_settings_id.

+
+ +
+
+uint32_t value¶
+

The value of this entry.

+
+ +
+ +
+
+nghttp2_settings¶
+

The SETTINGS frame. It has the following members:

+
+
+nghttp2_frame_hd hd¶
+

The frame header.

+
+ +
+
+size_t niv¶
+

The number of SETTINGS ID/Value pairs in iv.

+
+ +
+
+nghttp2_settings_entry *iv¶
+

The pointer to the array of SETTINGS ID/Value pair.

+
+ +
+ +
+
+nghttp2_push_promise¶
+

The PUSH_PROMISE frame. It has the following members:

+
+
+nghttp2_frame_hd hd¶
+

The frame header.

+
+ +
+
+nghttp2_nv *nva¶
+

The name/value pairs.

+
+ +
+
+size_t nvlen¶
+

The number of name/value pairs in nva.

+
+ +
+
+int32_t promised_stream_id¶
+

The promised stream ID

+
+ +
+ +
+
+nghttp2_ping¶
+

The PING frame. It has the following members:

+
+
+nghttp2_frame_hd hd¶
+

The frame header.

+
+ +
+
+uint8_t opaque_data[8]
+

The opaque data

+
+ +
+ +
+
+nghttp2_goaway¶
+

The GOAWAY frame. It has the following members:

+
+
+nghttp2_frame_hd hd¶
+

The frame header.

+
+ +
+
+int32_t last_stream_id¶
+

The last stream stream ID.

+
+ +
+
+nghttp2_error_code error_code¶
+

The error code. See nghttp2_error_code.

+
+ +
+
+uint8_t *opaque_data¶
+

The additional debug data

+
+ +
+
+size_t opaque_data_len¶
+

The length of opaque_data member.

+
+ +
+ +
+
+nghttp2_window_update¶
+

The WINDOW_UPDATE frame. It has the following members:

+
+
+nghttp2_frame_hd hd¶
+

The frame header.

+
+ +
+
+int32_t window_size_increment¶
+

The window size increment.

+
+ +
+ +
+
+nghttp2_frame¶
+

This union includes all frames to pass them to various function +calls as nghttp2_frame type. The CONTINUATION frame is omitted from +here because the library deals with it internally.

+
+
+nghttp2_frame_hd hd¶
+

The frame header, which is convenient to inspect frame header.

+
+ +
+
+nghttp2_data data¶
+

The DATA frame.

+
+ +
+
+nghttp2_headers headers¶
+

The HEADERS frame.

+
+ +
+
+nghttp2_priority priority¶
+

The PRIORITY frame.

+
+ +
+
+nghttp2_rst_stream rst_stream¶
+

The RST_STREAM frame.

+
+ +
+
+nghttp2_settings settings¶
+

The SETTINGS frame.

+
+ +
+
+nghttp2_push_promise push_promise¶
+

The PUSH_PROMISE frame.

+
+ +
+
+nghttp2_ping ping¶
+

The PING frame.

+
+ +
+
+nghttp2_goaway goaway¶
+

The GOAWAY frame.

+
+ +
+
+nghttp2_window_update window_update¶
+

The WINDOW_UPDATE frame.

+
+ +
+ +
+
+typedef ssize_t (*nghttp2_send_callback)(nghttp2_session *session, const uint8_t *data, size_t length, int flags, void *user_data)¶
+

Callback function invoked when session wants to send data to the +remote peer. The implementation of this function must send at most +length bytes of data stored in data. The flags is currently +not used and always 0. It must return the number of bytes sent if +it succeeds. If it cannot send any single byte without blocking, +it must return NGHTTP2_ERR_WOULDBLOCK. For other errors, it +must return NGHTTP2_ERR_CALLBACK_FAILURE. The user_data +pointer is the third argument passed in to the call to +nghttp2_session_client_new() or nghttp2_session_server_new().

+
+ +
+
+typedef ssize_t (*nghttp2_recv_callback)(nghttp2_session *session, uint8_t *buf, size_t length, int flags, void *user_data)¶
+

Callback function invoked when session wants to receive data from +the remote peer. The implementation of this function must read at +most length bytes of data and store it in buf. The flags is +currently not used and always 0. It must return the number of bytes +written in buf if it succeeds. If it cannot read any single byte +without blocking, it must return NGHTTP2_ERR_WOULDBLOCK. If +it gets EOF before it reads any single byte, it must return +NGHTTP2_ERR_EOF. For other errors, it must return +NGHTTP2_ERR_CALLBACK_FAILURE. Returning 0 is treated as +NGHTTP2_ERR_WOULDBLOCK. The user_data pointer is the +third argument passed in to the call to +nghttp2_session_client_new() or nghttp2_session_server_new().

+
+ +
+
+typedef int (*nghttp2_on_frame_recv_callback)(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)¶
+

Callback function invoked by nghttp2_session_recv() when a aframe +is received. The user_data pointer is the third argument passed +in to the call to nghttp2_session_client_new() or +nghttp2_session_server_new().

+

If frame is HEADERS or PUSH_PROMISE, the nva and nvlen +member of their data structure are always NULL and 0 +respectively. The header name/value pairs are emitted via +nghttp2_on_header_callback.

+

For HEADERS, PUSH_PROMISE and DATA frames, this callback may be +called after stream is closed (see +nghttp2_on_stream_close_callback). The application should +check that stream is still alive using its own stream management or +nghttp2_session_get_stream_user_data().

+

Only HEADERS and DATA frame can signal the end of incoming data. If +frame->hd.flags & NGHTTP2_FLAG_END_STREAM is nonzero, the +frame is the last frame from the remote peer in this stream.

+

The implementation of this function must return 0 if it +succeeds. If nonzero value is returned, it is treated as fatal +error and nghttp2_session_recv() and nghttp2_session_mem_recv() +functions immediately return NGHTTP2_ERR_CALLBACK_FAILURE.

+
+ +
+
+typedef int (*nghttp2_on_invalid_frame_recv_callback)(nghttp2_session *session, const nghttp2_frame *frame, nghttp2_error_code error_code, void *user_data)¶
+

Callback function invoked by nghttp2_session_recv() when an +invalid non-DATA frame is received. The error_code is one of the +nghttp2_error_code and indicates the error. When this +callback function is invoked, the library automatically submits +either RST_STREAM or GOAWAY frame. The user_data pointer is the +third argument passed in to the call to +nghttp2_session_client_new() or nghttp2_session_server_new().

+

If frame is HEADERS or PUSH_PROMISE, the nva and nvlen +member of their data structure are always NULL and 0 +respectively.

+

The implementation of this function must return 0 if it +succeeds. If nonzero is returned, it is treated as fatal error and +nghttp2_session_recv() and nghttp2_session_send() functions +immediately return NGHTTP2_ERR_CALLBACK_FAILURE.

+
+ +
+
+typedef int (*nghttp2_on_data_chunk_recv_callback)(nghttp2_session *session, uint8_t flags, int32_t stream_id, const uint8_t *data, size_t len, void *user_data)¶
+

Callback function invoked when a chunk of data in DATA frame is +received. The stream_id is the stream ID this DATA frame belongs +to. The flags is the flags of DATA frame which this data chunk is +contained. (flags & NGHTTP2_FLAG_END_STREAM) != 0 does not +necessarily mean this chunk of data is the last one in the +stream. You should use nghttp2_on_frame_recv_callback to +know all data frames are received. The user_data pointer is the +third argument passed in to the call to +nghttp2_session_client_new() or nghttp2_session_server_new().

+

If the application uses nghttp2_session_mem_recv(), it can return +NGHTTP2_ERR_PAUSE to make nghttp2_session_mem_recv() +return without processing further input bytes. The memory by +pointed by the data is retained until +nghttp2_session_mem_recv() or nghttp2_session_recv() is +called. The application must retain the input bytes which was used +to produce the data parameter, because it may refer to the memory +region included in the input bytes.

+

The implementation of this function must return 0 if it +succeeds. If nonzero is returned, it is treated as fatal error and +nghttp2_session_recv() and nghttp2_session_mem_recv() functions +immediately return NGHTTP2_ERR_CALLBACK_FAILURE.

+
+ +
+
+typedef int (*nghttp2_before_frame_send_callback)(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)¶
+

Callback function invoked before the non-DATA frame frame is +sent. This may be useful, for example, to know the stream ID of +HEADERS and PUSH_PROMISE frame (see also +nghttp2_session_get_stream_user_data()), which is not assigned +when it was queued. The user_data pointer is the third argument +passed in to the call to nghttp2_session_client_new() or +nghttp2_session_server_new().

+

The implementation of this function must return 0 if it +succeeds. If nonzero is returned, it is treated as fatal error and +nghttp2_session_recv() and nghttp2_session_send() functions +immediately return NGHTTP2_ERR_CALLBACK_FAILURE.

+
+ +
+
+typedef int (*nghttp2_on_frame_send_callback)(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)¶
+

Callback function invoked after the frame frame is sent. The +user_data pointer is the third argument passed in to the call to +nghttp2_session_client_new() or nghttp2_session_server_new().

+

The implementation of this function must return 0 if it +succeeds. If nonzero is returned, it is treated as fatal error and +nghttp2_session_recv() and nghttp2_session_send() functions +immediately return NGHTTP2_ERR_CALLBACK_FAILURE.

+
+ +
+
+typedef int (*nghttp2_on_frame_not_send_callback)(nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code, void *user_data)¶
+

Callback function invoked after the non-DATA frame frame is not +sent because of the error. The error is indicated by the +lib_error_code, which is one of the values defined in +nghttp2_error. The user_data pointer is the third +argument passed in to the call to nghttp2_session_client_new() or +nghttp2_session_server_new().

+

The implementation of this function must return 0 if it +succeeds. If nonzero is returned, it is treated as fatal error and +nghttp2_session_recv() and nghttp2_session_send() functions +immediately return NGHTTP2_ERR_CALLBACK_FAILURE.

+
+ +
+
+typedef int (*nghttp2_on_stream_close_callback)(nghttp2_session *session, int32_t stream_id, nghttp2_error_code error_code, void *user_data)¶
+

Callback function invoked when the stream stream_id is +closed. The reason of closure is indicated by the error_code. The +stream_user_data, which was specified in nghttp2_submit_request() +or nghttp2_submit_headers(), is still available in this +function. The user_data pointer is the third argument passed in +to the call to nghttp2_session_client_new() or +nghttp2_session_server_new().

+

The implementation of this function must return 0 if it +succeeds. If nonzero is returned, it is treated as fatal error and +nghttp2_session_recv() and nghttp2_session_send() functions +immediately return NGHTTP2_ERR_CALLBACK_FAILURE.

+
+ +
+
+typedef int (*nghttp2_on_unknown_frame_recv_callback)(nghttp2_session *session, const uint8_t *head, size_t headlen, const uint8_t *payload, size_t payloadlen, void *user_data)¶
+

Callback function invoked when the received frame type is +unknown. The head is the pointer to the header of the received +frame. The headlen is the length of the head. According to the +spec, the headlen is always 8. In other words, the head is the +first 8 bytes of the received frame. The payload is the pointer +to the data portion of the received frame. The payloadlen is the +length of the payload. This is the data after the length +field. The user_data pointer is the third argument passed in to +the call to nghttp2_session_client_new() or +nghttp2_session_server_new().

+

The implementation of this function must return 0 if it +succeeds. If nonzero is returned, it is treated as fatal error and +nghttp2_session_recv() and nghttp2_session_send() functions +immediately return NGHTTP2_ERR_CALLBACK_FAILURE.

+
+ +
+
+typedef int (*nghttp2_on_begin_headers_callback)(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)¶
+

Callback function invoked when the reception of header block in +HEADERS or PUSH_PROMISE is started. Each header name/value pair +will be emitted by nghttp2_on_header_callback.

+

The frame->hd.flags may not have +NGHTTP2_FLAG_END_HEADERS flag set, which indicates that one +or more CONTINUATION frames are involved. But the application does +not need to care about that because the header name/value pairs are +emitted transparently regardless of CONTINUATION frames.

+

The implementation of this function must return 0 if it succeeds or +NGHTTP2_ERR_CALLBACK_FAILURE. If nonzero value other than +NGHTTP2_ERR_CALLBACK_FAILURE is returned, it is treated as +if NGHTTP2_ERR_CALLBACK_FAILURE is returned. If +NGHTTP2_ERR_CALLBACK_FAILURE is returned, +nghttp2_session_mem_recv() function will immediately return +NGHTTP2_ERR_CALLBACK_FAILURE.

+
+ +
+
+typedef int (*nghttp2_on_header_callback)(nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, void *user_data)¶
+

Callback function invoked when a header name/value pair is received +for the frame. When this callback is invoked, frame->hd.type +is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE. +After all header name/value pairs are processed with this callback, +and no error has been detected, +nghttp2_on_frame_recv_callback will be invoked. If there +is an error in decompression, +nghttp2_on_frame_recv_callback for the frame will not be +invoked.

+

The name may be NULL if the namelen is 0. The same thing +can be said about the value.

+

Please note that nghttp2 library does not perform any validity +check against the name and the value. For example, the +namelen could be 0, and/or the value contains 0x0a or +0x0d. The application must check them if it matters. The +helper function nghttp2_check_header_name() and +nghttp2_check_header_value() provide simple validation against +HTTP2 header field construction rule.

+

One more thing to note is that the value may contain NULL +(0x00) characters. It is used to concatenate header values +which share the same header field name. The application should +split these values if it wants to get individual value. This +concatenation is used in order to keep the ordering of headers.

+

If the application uses nghttp2_session_mem_recv(), it can return +NGHTTP2_ERR_PAUSE to make nghttp2_session_mem_recv() +return without processing further input bytes. The memory pointed +by frame, name and value parameters are retained until +nghttp2_session_mem_recv() or nghttp2_session_recv() is +called. The application must retain the input bytes which was used +to produce these parameters, because it may refer to the memory +region included in the input bytes.

+

Returning NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE will close +the stream by issuing RST_STREAM with +NGHTTP2_INTERNAL_ERROR. In this case, +nghttp2_on_frame_recv_callback will not be invoked.

+

The implementation of this function must return 0 if it +succeeds. It may return NGHTTP2_ERR_PAUSE or +NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE. For other critical +failures, it must return NGHTTP2_ERR_CALLBACK_FAILURE. If +the other nonzero value is returned, it is treated as +NGHTTP2_ERR_CALLBACK_FAILURE. If +NGHTTP2_ERR_CALLBACK_FAILURE is returned, +nghttp2_session_recv() and nghttp2_session_mem_recv() functions +immediately return NGHTTP2_ERR_CALLBACK_FAILURE.

+
+ +
+
+nghttp2_session_callbacks¶
+

Callback functions.

+
+
+nghttp2_send_callback send_callback¶
+

Callback function invoked when the session wants to send data +to the remote peer.

+
+ +
+
+nghttp2_recv_callback recv_callback¶
+

Callback function invoked when the session wants to receive +data from the remote peer.

+
+ +
+
+nghttp2_on_frame_recv_callback on_frame_recv_callback¶
+

Callback function invoked by nghttp2_session_recv() when a +frame is received.

+
+ +
+
+nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback¶
+

Callback function invoked by nghttp2_session_recv() when an +invalid non-DATA frame is received.

+
+ +
+
+nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback¶
+

Callback function invoked when a chunk of data in DATA frame is +received.

+
+ +
+
+nghttp2_before_frame_send_callback before_frame_send_callback¶
+

Callback function invoked before a non-DATA frame is sent.

+
+ +
+
+nghttp2_on_frame_send_callback on_frame_send_callback¶
+

Callback function invoked after a frame is sent.

+
+ +
+
+nghttp2_on_frame_not_send_callback on_frame_not_send_callback¶
+

The callback function invoked when a non-DATA frame is not sent +because of an error.

+
+ +
+
+nghttp2_on_stream_close_callback on_stream_close_callback¶
+

Callback function invoked when the stream is closed.

+
+ +
+
+nghttp2_on_unknown_frame_recv_callback on_unknown_frame_recv_callback¶
+

Callback function invoked when the received frame type is +unknown.

+
+ +
+
+nghttp2_on_begin_headers_callback on_begin_headers_callback¶
+

Callback function invoked when the reception of header block in +HEADERS or PUSH_PROMISE is started.

+
+ +
+
+nghttp2_on_header_callback on_header_callback¶
+

Callback function invoked when a header name/value pair is +received.

+
+ +
+ +
+
+nghttp2_opt_set¶
+

Struct to store option values for nghttp2_session.

+
+
+uint32_t peer_max_concurrent_streams¶
+

NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS

+
+ +
+
+uint8_t no_auto_stream_window_update¶
+

NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE

+
+ +
+
+uint8_t no_auto_connection_window_update¶
+

NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE

+
+ +
+ +
+
+nghttp2_gzip¶
+

The gzip stream to inflate data. The details of this structure are +intentionally hidden from the public API.

+
+ +
+
+

Functions¶

+
+
+int nghttp2_session_client_new(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data)¶
+

Initializes *session_ptr for client use. The all members of +callbacks are copied to *session_ptr. Therefore *session_ptr +does not store callbacks. user_data is an arbitrary user +supplied data, which will be passed to the callback functions.

+

The nghttp2_session_callbacks.send_callback must be +specified. If the application code uses nghttp2_session_recv(), +the nghttp2_session_callbacks.recv_callback must be +specified. The other members of callbacks can be NULL.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_session_server_new(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data)¶
+

Initializes *session_ptr for server use. The all members of +callbacks are copied to *session_ptr. Therefore *session_ptr +does not store callbacks. user_data is an arbitrary user +supplied data, which will be passed to the callback functions.

+

The nghttp2_session_callbacks.send_callback must be +specified. If the application code uses nghttp2_session_recv(), +the nghttp2_session_callbacks.recv_callback must be +specified. The other members of callbacks can be NULL.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_session_client_new2(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data, uint32_t opt_set_mask, const nghttp2_opt_set *opt_set)¶
+

Like nghttp2_session_client_new(), but with additional options +specified in the opt_set. The caller must set bitwise-OR of +nghttp2_opt for given options. For example, if it +specifies NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE and +NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS in the opt_set, +the opt_set_mask should be +NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE | +NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS.

+

If the opt_set_mask is 0, the opt_set could be NULL safely +and the call is equivalent to nghttp2_session_client_new().

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_session_server_new2(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data, uint32_t opt_set_mask, const nghttp2_opt_set *opt_set)¶
+

Like nghttp2_session_server_new(), but with additional options +specified in the opt_set. The caller must set bitwise-OR of +nghttp2_opt for given options. For example, if it +specifies NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE and +NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS in the opt_set, +the opt_set_mask should be +NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE | +NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS.

+

If the opt_set_mask is 0, the opt_set could be NULL safely +and the call is equivalent to nghttp2_session_server_new().

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+void nghttp2_session_del(nghttp2_session *session)¶
+

Frees any resources allocated for session. If session is +NULL, this function does nothing.

+
+ +
+
+int nghttp2_session_send(nghttp2_session *session)¶
+

Sends pending frames to the remote peer.

+

This function retrieves the highest prioritized frame from the +outbound queue and sends it to the remote peer. It does this as +many as possible until the user callback +nghttp2_session_callbacks.send_callback returns +NGHTTP2_ERR_WOULDBLOCK or the outbound queue becomes empty. +This function calls several callback functions which are passed +when initializing the session. Here is the simple time chart +which tells when each callback is invoked:

+
    +
  1. Get the next frame to send from outbound queue.
  2. +
  3. Prepare transmission of the frame.
  4. +
  5. If the control frame cannot be sent because some preconditions +are not met (e.g., request HEADERS cannot be sent after +GOAWAY), +nghttp2_session_callbacks.on_frame_not_send_callback is +invoked. Abort the following steps.
  6. +
  7. If the frame is request HEADERS, the stream is opened +here.
  8. +
  9. nghttp2_session_callbacks.before_frame_send_callback is +invoked.
  10. +
  11. nghttp2_session_callbacks.send_callback is invoked one +or more times to send the frame.
  12. +
  13. nghttp2_session_callbacks.on_frame_send_callback is +invoked.
  14. +
  15. If the transmission of the frame triggers closure of the stream, +the stream is closed and +nghttp2_session_callbacks.on_stream_close_callback is +invoked.
  16. +
+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
NGHTTP2_ERR_CALLBACK_FAILURE
+
The callback function failed.
+
+
+ +
+
+int nghttp2_session_recv(nghttp2_session *session)¶
+

Receives frames from the remote peer.

+

This function receives as many frames as possible until the user +callback nghttp2_session_callbacks.recv_callback returns +NGHTTP2_ERR_WOULDBLOCK. This function calls several +callback functions which are passed when initializing the +session. Here is the simple time chart which tells when each +callback is invoked:

+
    +
  1. nghttp2_session_callbacks.recv_callback is invoked one +or more times to receive frame header.
  2. +
  3. If the frame is DATA frame:
      +
    1. nghttp2_session_callbacks.recv_callback is invoked +to receive DATA payload. For each chunk of data, +nghttp2_session_callbacks.on_data_chunk_recv_callback +is invoked.
    2. +
    3. If one DATA frame is completely received, +nghttp2_session_callbacks.on_frame_recv_callback is +invoked. If the reception of the frame triggers the +closure of the stream, +nghttp2_session_callbacks.on_stream_close_callback +is invoked.
    4. +
    +
  4. +
  5. If the frame is the control frame:
      +
    1. nghttp2_session_callbacks.recv_callback is invoked +one or more times to receive whole frame.
    2. +
    3. If the received frame is valid, then following actions are +taken. If the frame is either HEADERS or PUSH_PROMISE, +nghttp2_session_callbacks.on_begin_headers_callback +is invoked. Then +nghttp2_session_callbacks.on_header_callback is +invoked for each header name/value pair. After all name/value +pairs are emitted successfully, +nghttp2_session_callbacks.on_frame_recv_callback is +invoked. For other frames, +nghttp2_session_callbacks.on_frame_recv_callback is +invoked. +If the reception of the frame triggers the closure of the +stream, +nghttp2_session_callbacks.on_stream_close_callback +is invoked.
    4. +
    5. If the received frame is unpacked but is interpreted as +invalid, +nghttp2_session_callbacks.on_invalid_frame_recv_callback +is invoked.
    6. +
    7. If the received frame type is unknown, +nghttp2_session_callbacks.on_unknown_frame_recv_callback +is invoked.
    8. +
    +
  6. +
+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_EOF
+
The remote peer did shutdown on the connection.
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
NGHTTP2_ERR_CALLBACK_FAILURE
+
The callback function failed.
+
+
+ +
+
+ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, size_t inlen)¶
+

Processes data in as an input from the remote endpoint. The +inlen indicates the number of bytes in the in.

+

This function behaves like nghttp2_session_recv() except that it +does not use nghttp2_session_callbacks.recv_callback to +receive data; the in is the only data for the invocation of this +function. If all bytes are processed, this function returns. The +other callbacks are called in the same way as they are in +nghttp2_session_recv().

+

In the current implementation, this function always tries to +processes all input data unless either an error occurs or +NGHTTP2_ERR_PAUSE is returned from +nghttp2_session_callbacks.on_header_callback or +nghttp2_session_callbacks.on_data_chunk_recv_callback. +If NGHTTP2_ERR_PAUSE is used, the return value includes the +number of bytes which was used to produce the data or frame for the +callback.

+

This function returns the number of processed bytes, or one of the +following negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
NGHTTP2_ERR_CALLBACK_FAILURE
+
The callback function failed.
+
+
+ +
+
+int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id)¶
+

Puts back previously deferred DATA frame in the stream stream_id +to the outbound queue.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_INVALID_ARGUMENT
+
The stream does not exist or no deferred data exist.
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_session_want_read(nghttp2_session *session)¶
+

Returns nonzero value if session wants to receive data from the +remote peer.

+

If both nghttp2_session_want_read() and +nghttp2_session_want_write() return 0, the application should +drop the connection.

+
+ +
+
+int nghttp2_session_want_write(nghttp2_session *session)¶
+

Returns nonzero value if session wants to send data to the remote +peer.

+

If both nghttp2_session_want_read() and +nghttp2_session_want_write() return 0, the application should +drop the connection.

+
+ +
+
+void* nghttp2_session_get_stream_user_data(nghttp2_session *session, int32_t stream_id)¶
+

Returns stream_user_data for the stream stream_id. The +stream_user_data is provided by nghttp2_submit_request(), +nghttp2_submit_headers() or +nghttp2_session_set_stream_user_data(). Unless it is set using +nghttp2_session_set_stream_user_data(), if the stream is +initiated by the remote endpoint, stream_user_data is always +NULL. If the stream does not exist, this function returns +NULL.

+
+ +
+
+int nghttp2_session_set_stream_user_data(nghttp2_session *session, int32_t stream_id, void *stream_user_data)¶
+

Sets the stream_user_data to the stream denoted by the +stream_id. If a stream user data is already set to the stream, it +is replaced with the stream_user_data. It is valid to specify +NULL in the stream_user_data, which nullifies the associated +data pointer.

+

It is valid to set the stream_user_data to the stream reserved by +PUSH_PROMISE frame.

+

This function returns 0 if it succeeds, or one of following +negative error codes:

+
+
NGHTTP2_ERR_INVALID_ARGUMENT
+
The stream does not exist
+
+
+ +
+
+size_t nghttp2_session_get_outbound_queue_size(nghttp2_session *session)¶
+

Returns the number of frames in the outbound queue. This does not +include the deferred DATA frames.

+
+ +
+
+int32_t nghttp2_session_get_stream_effective_recv_data_length(nghttp2_session *session, int32_t stream_id)¶
+

Returns the number of DATA payload in bytes received without +WINDOW_UPDATE transmission for the stream stream_id. The local +(receive) window size can be adjusted by +nghttp2_submit_window_update(). This function takes into account +that and returns effective data length. In particular, if the +local window size is reduced by submitting negative +window_size_increment with nghttp2_submit_window_update(), this +function returns the number of bytes less than actually received.

+

If flow control is disabled for that stream, this function returns +0.

+

This function returns -1 if it fails.

+
+ +
+
+int32_t nghttp2_session_get_stream_effective_local_window_size(nghttp2_session *session, int32_t stream_id)¶
+

Returns the local (receive) window size for the stream +stream_id. The local window size can be adjusted by +nghttp2_submit_window_update(). This function takes into account +that and returns effective window size.

+

This function returns -1 if it fails.

+
+ +
+
+int32_t nghttp2_session_get_effective_recv_data_length(nghttp2_session *session)¶
+

Returns the number of DATA payload in bytes received without +WINDOW_UPDATE transmission for a connection. The local (receive) +window size can be adjusted by +nghttp2_submit_window_update(). This function takes into account +that and returns effective data length. In particular, if the local +window size is reduced by submitting negative window_size_increment +with nghttp2_submit_window_update(), this function returns the +number of bytes less than actually received.

+

If flow control is disabled for a connection, this function returns +0.

+

This function returns -1 if it fails.

+
+ +
+
+int32_t nghttp2_session_get_effective_local_window_size(nghttp2_session *session)¶
+

Returns the local (receive) window size for a connection. The local +window size can be adjusted by +nghttp2_submit_window_update(). This function takes into account +that and returns effective window size.

+

This function returns -1 if it fails.

+
+ +
+
+int nghttp2_session_terminate_session(nghttp2_session *session, nghttp2_error_code error_code)¶
+

Signals the session so that the connection should be terminated.

+

GOAWAY frame with the given error_code will be submitted if it +has not been transmitted. After the transmission, both +nghttp2_session_want_read() and nghttp2_session_want_write() +return 0. If GOAWAY frame has already transmitted at the time when +this function is invoked, nghttp2_session_want_read() and +nghttp2_session_want_write() returns 0 immediately after this +function succeeds.

+

This function should be called when the connection should be +terminated after sending GOAWAY. If the remaining streams should be +processed after GOAWAY, use nghttp2_submit_goaway() instead.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_session_upgrade(nghttp2_session *session, const uint8_t *settings_payload, size_t settings_payloadlen, void *stream_user_data)¶
+

Performs post-process of HTTP Upgrade request. This function can be +called from both client and server, but the behavior is very +different in each other.

+

If called from client side, the settings_payload must be the +value sent in HTTP2-Settings header field and must be decoded +by base64url decoder. The settings_payloadlen is the length of +settings_payload. The settings_payload is unpacked and its +setting values will be submitted using +nghttp2_submit_settings(). This means that the client application +code does not need to submit SETTINGS by itself. The stream with +stream ID=1 is opened and the stream_user_data is used for its +stream_user_data. The opened stream becomes half-closed (local) +state.

+

If called from server side, the settings_payload must be the +value received in HTTP2-Settings header field and must be +decoded by base64url decoder. The settings_payloadlen is the +length of settings_payload. It is treated as if the SETTINGS +frame with that payload is received. Thus, callback functions for +the reception of SETTINGS frame will be invoked. The stream with +stream ID=1 is opened. The stream_user_data is ignored. The +opened stream becomes half-closed (remote).

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
NGHTTP2_ERR_INVALID_ARGUMENT
+
The settings_payload is badly formed.
+
NGHTTP2_ERR_PROTO
+
The stream ID 1 is already used or closed; or is not available; +or the settings_payload does not include both +NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS and +NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE.
+
+
+ +
+
+ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen, const nghttp2_settings_entry *iv, size_t niv)¶
+

Serializes the SETTINGS values iv in the buf. The size of the +buf is specified by buflen. The number of entries in the iv +array is given by niv. The required space in buf for the niv +entries is 8*niv bytes and if the given buffer is too small, an +error is returned. This function is used mainly for creating a +SETTINGS payload to be sent with the HTTP2-Settings header +field in an HTTP Upgrade request. The data written in buf is NOT +base64url encoded and the application is responsible for encoding.

+

This function returns the number of bytes written in buf, or one +of the following negative error codes:

+
+
NGHTTP2_ERR_INVALID_ARGUMENT
+
The iv contains duplicate settings ID or invalid value.
+
NGHTTP2_ERR_INSUFF_BUFSIZE
+
The provided buflen size is too small to hold the output.
+
+
+ +
+
+const char* nghttp2_strerror(int lib_error_code)¶
+

Returns string describing the lib_error_code. The +lib_error_code must be one of the nghttp2_error.

+
+ +
+
+int nghttp2_submit_request(nghttp2_session *session, int32_t pri, const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd, void *stream_user_data)¶
+

Submits HEADERS frame and optionally one or more DATA frames.

+

The pri is priority of this request. 0 is the highest priority +value and NGHTTP2_PRI_LOWEST is the lowest value.

+

The nva is an array of name/value pair nghttp2_nv with +nvlen elements. The value is opaque sequence of bytes and +therefore can contain NULL byte (0x0). If the application requires +that the ordering of values for a single header field name +appearing in different header fields, it has to concatenate them +using NULL byte (0x0) before passing them to this function.

+

HTTP/2.0 specification has requirement about header fields in the +request HEADERS. See the specification for more details.

+

This function creates copies of all name/value pairs in nva. It +also lower-cases all names in nva.

+

If data_prd is not NULL, it provides data which will be sent +in subsequent DATA frames. In this case, a method that allows +request message bodies +(http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9) must +be specified with :method key in nva (e.g. POST). This +function does not take ownership of the data_prd. The function +copies the members of the data_prd. If data_prd is NULL, +HEADERS have END_STREAM set. The stream_user_data is data +associated to the stream opened by this request and can be an +arbitrary pointer, which can be retrieved later by +nghttp2_session_get_stream_user_data().

+

Since the library reorders the frames and tries to send the highest +prioritized one first and the HTTP/2.0 specification requires the +stream ID must be strictly increasing, the stream ID of this +request cannot be known until it is about to sent. To know the +stream ID of the request, the application can use +nghttp2_session_callbacks.before_frame_send_callback. This +callback is called just before the frame is sent. For HEADERS +frame, the argument frame has the stream ID assigned. Also since +the stream is already opened, +nghttp2_session_get_stream_user_data() can be used to get +stream_user_data to identify which HEADERS we are processing.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_INVALID_ARGUMENT
+
The pri is invalid
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd)¶
+

Submits response HEADERS frame and optionally one or more DATA +frames against the stream stream_id.

+

The nva is an array of name/value pair nghttp2_nv with +nvlen elements. The value is opaque sequence of bytes and +therefore can contain NULL byte (0x0). If the application requires +that the ordering of values for a single header field name +appearing in different header fields, it has to concatenate them +using NULL byte (0x0) before passing them to this function.

+

HTTP/2.0 specification has requirement about header fields in the +response HEADERS. See the specification for more details.

+

This function creates copies of all name/value pairs in nva. It +also lower-cases all names in nva.

+

If data_prd is not NULL, it provides data which will be sent +in subsequent DATA frames. This function does not take ownership +of the data_prd. The function copies the members of the +data_prd. If data_prd is NULL, HEADERS will have +END_STREAM flag set.

+

This method can be used as normal HTTP response and push +response. When pushing a resource using this function, the +session must be configured using nghttp2_session_server_new() +or its variants and the target stream denoted by the stream_id +must be reserved using nghttp2_submit_push_promise().

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, int32_t stream_id, int32_t pri, const nghttp2_nv *nva, size_t nvlen, void *stream_user_data)¶
+

Submits HEADERS frame. The flags is bitwise OR of the +following values:

+ +

If flags includes NGHTTP2_FLAG_END_STREAM, this frame has +END_STREAM flag set. The library does not support header +continuation and the HEADERS frame always has +NGHTTP2_FLAG_END_HEADERS flag set regardless of the flags +value.

+

If the stream_id is -1, this frame is assumed as request (i.e., +request HEADERS frame which opens new stream). In this case, the +actual stream ID is assigned just before the frame is sent. For +response, specify stream ID in stream_id.

+

The pri is priority of this request.

+

The nva is an array of name/value pair nghttp2_nv with +nvlen elements. The value is opaque sequence of bytes and +therefore can contain NULL byte (0x0). If the application requires +that the ordering of values for a single header field name +appearing in different header fields, it has to concatenate them +using NULL byte (0x0) before passing them to this function.

+

This function creates copies of all name/value pairs in nva. It +also lower-cases all names in nva.

+

The stream_user_data is a pointer to an arbitrary data which is +associated to the stream this frame will open. Therefore it is only +used if this frame opens streams, in other words, it changes stream +state from idle or reserved to open.

+

This function is low-level in a sense that the application code can +specify flags directly. For usual HTTP request, +nghttp2_submit_request() is useful.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_INVALID_ARGUMENT
+
The pri is invalid
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_data_provider *data_prd)¶
+

Submits one or more DATA frames to the stream stream_id. The +data to be sent are provided by data_prd. If flags contains +NGHTTP2_FLAG_END_STREAM, the last DATA frame has END_STREAM +flag set.

+

This function does not take ownership of the data_prd. The +function copies the members of the data_prd.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags, int32_t stream_id, int32_t pri)¶
+

Submits PRIORITY frame to change the priority of stream stream_id +to the priority value pri.

+

The flags is currently ignored and should be +NGHTTP2_FLAG_NONE.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
NGHTTP2_ERR_INVALID_ARGUMENT
+
The pri is negative.
+
+
+ +
+
+int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags, int32_t stream_id, nghttp2_error_code error_code)¶
+

Submits RST_STREAM frame to cancel/reject the stream stream_id +with the error code error_code.

+

The flags is currently ignored and should be +NGHTTP2_FLAG_NONE.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags, const nghttp2_settings_entry *iv, size_t niv)¶
+

Stores local settings and submits SETTINGS frame. The iv is the +pointer to the array of nghttp2_settings_entry. The niv +indicates the number of nghttp2_settings_entry.

+

The flags is currently ignored and should be +NGHTTP2_FLAG_NONE.

+

This function does not take ownership of the iv. This function +copies all the elements in the iv.

+

While updating individual stream’s local window size, if the window +size becomes strictly larger than NGHTTP2_MAX_WINDOW_SIZE, +RST_STREAM is issued against such a stream.

+

SETTINGS with NGHTTP2_FLAG_ACK is automatically submitted +by the library and application could not send it at its will.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_INVALID_ARGUMENT
+
The iv contains invalid value (e.g., attempting to re-enable +flow control).
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_nv *nva, size_t nvlen)¶
+

Submits PUSH_PROMISE frame. The flags is currently ignored and +the resulting PUSH_PROMISE frame always has +NGHTTP2_FLAG_END_PUSH_PROMISE flag set due to the lack of +header continuation support in the library.

+

The stream_id must be client initiated stream ID.

+

The nva is an array of name/value pair nghttp2_nv with +nvlen elements. The value is opaque sequence of bytes and +therefore can contain NULL byte (0x0). If the application requires +that the ordering of values for a single header field name +appearing in different header fields, it has to concatenate them +using NULL byte (0x0) before passing them to this function.

+

This function creates copies of all name/value pairs in nva. It +also lower-cases all names in nva.

+

Since the library reorders the frames and tries to send the highest +prioritized one first and the HTTP/2.0 specification requires the +stream ID must be strictly increasing, the promised stream ID +cannot be known until it is about to sent. To know the promised +stream ID, the application can use +nghttp2_session_callbacks.before_frame_send_callback. This +callback is called just before the frame is sent. For PUSH_PROMISE +frame, the argument frame has the promised stream ID assigned.

+

The client side can use this function to send PUSH_PROMISE to the +server. But in normal HTTP usage, the server may treat it error.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags, uint8_t *opaque_data)¶
+

Submits PING frame. You don’t have to send PING back when you +received PING frame. The library automatically submits PING frame +in this case.

+

The flags is currently ignored and should be +NGHTTP2_FLAG_NONE.

+

If the opaque_data is non NULL, then it should point to the 8 +bytes array of memory to specify opaque data to send with PING +frame. If the opaque_data is NULL, zero-cleared 8 bytes will +be sent as opaque data.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags, nghttp2_error_code error_code, uint8_t *opaque_data, size_t opaque_data_len)¶
+

Submits GOAWAY frame with the error code error_code.

+

The flags is currently ignored and should be +NGHTTP2_FLAG_NONE.

+

If the opaque_data is not NULL and opaque_data_len is not +zero, those data will be sent as additional debug data. The +library makes a copy of the memory region pointed by opaque_data +with the length opaque_data_len, so the caller does not need to +keep this memory after the return of this function. If the +opaque_data_len is 0, the opaque_data could be NULL.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags, int32_t stream_id, int32_t window_size_increment)¶
+

Submits WINDOW_UPDATE frame.

+

The flags is currently ignored and should be +NGHTTP2_FLAG_NONE.

+

If the window_size_increment is positive, the WINDOW_UPDATE with +that value as window_size_increment is queued. If the +window_size_increment is larger than the received bytes from the +remote endpoint, the local window size is increased by that +difference.

+

If the window_size_increment is negative, the local window size +is decreased by -window_size_increment. If +NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE (or +NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE if stream_id +is 0) is not set and the library decided that the WINDOW_UPDATE +should be submitted, then WINDOW_UPDATE is queued with the current +received bytes count.

+

If the window_size_increment is 0, the function does nothing and +returns 0.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_FLOW_CONTROL
+
The local window size overflow or gets negative.
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+int nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs)¶
+

Compares lhs->name with lhs->namelen bytes and rhs->name with +rhs->namelen bytes. Returns negative integer if lhs->name is found +to be less than rhs->name; or returns positive integer if lhs->name +is found to be greater than rhs->name; or returns 0 otherwise.

+
+ +
+
+int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen)¶
+

A helper function for dealing with NPN in client side or ALPN in +server side. The in contains peer’s protocol list in preferable +order. The format of in is length-prefixed and not +null-terminated. For example, HTTP-draft-04/2.0 and +http/1.1 stored in in like this:

+
in[0] = 17
+in[1..17] = "HTTP-draft-04/2.0"
+in[18] = 8
+in[19..26] = "http/1.1"
+inlen = 27
+
+
+

The selection algorithm is as follows:

+
    +
  1. If peer’s list contains HTTP/2.0 protocol the library supports, +it is selected and returns 1. The following step is not taken.
  2. +
  3. If peer’s list contains http/1.1, this function selects +http/1.1 and returns 0. The following step is not taken.
  4. +
  5. This function selects nothing and returns -1. (So called +non-overlap case). In this case, out and outlen are left +untouched.
  6. +
+

Selecting HTTP-draft-04/2.0 means that HTTP-draft-04/2.0 is +written into *out and its length (which is 17) is +assigned to *outlen.

+

For ALPN, refer to +http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04

+

See http://technotes.googlecode.com/git/nextprotoneg.html for more +details about NPN.

+

For NPN, to use this method you should do something like:

+
static int select_next_proto_cb(SSL* ssl,
+                                unsigned char **out,
+                                unsigned char *outlen,
+                                const unsigned char *in,
+                                unsigned int inlen,
+                                void *arg)
+{
+    int rv;
+    rv = nghttp2_select_next_protocol(out, outlen, in, inlen);
+    if(rv == 1) {
+        ((MyType*)arg)->http2_selected = 1;
+    }
+    return SSL_TLSEXT_ERR_OK;
+}
+...
+SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, my_obj);
+
+
+
+ +
+
+int nghttp2_gzip_inflate_new(nghttp2_gzip **inflater_ptr)¶
+

A helper function to set up a per request gzip stream to inflate data.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_GZIP
+
The initialization of gzip stream failed.
+
NGHTTP2_ERR_NOMEM
+
Out of memory.
+
+
+ +
+
+void nghttp2_gzip_inflate_del(nghttp2_gzip *inflater)¶
+

Frees the inflate stream. The inflater may be NULL.

+
+ +
+
+int nghttp2_gzip_inflate(nghttp2_gzip *inflater, uint8_t *out, size_t *outlen_ptr, const uint8_t *in, size_t *inlen_ptr)¶
+

Inflates data in in with the length *inlen_ptr and stores the +inflated data to out which has allocated size at least +*outlen_ptr. On return, *outlen_ptr is updated to represent +the number of data written in out. Similarly, *inlen_ptr is +updated to represent the number of input bytes processed.

+

This function returns 0 if it succeeds, or one of the following +negative error codes:

+
+
NGHTTP2_ERR_GZIP
+
The inflation of gzip stream failed.
+
+

The example follows:

+
void on_data_chunk_recv_callback(nghttp2_session *session,
+                                 uint8_t flags,
+                                 int32_t stream_id,
+                                 const uint8_t *data, size_t len,
+                                 void *user_data)
+{
+    ...
+    req = nghttp2_session_get_stream_user_data(session, stream_id);
+    nghttp2_gzip *inflater = req->inflater;
+    while(len > 0) {
+        uint8_t out[MAX_OUTLEN];
+        size_t outlen = MAX_OUTLEN;
+        size_t tlen = len;
+        int rv;
+        rv = nghttp2_gzip_inflate(inflater, out, &outlen, data, &tlen);
+        if(rv != 0) {
+            nghttp2_submit_rst_stream(session, stream_id,
+                                      NGHTTP2_INTERNAL_ERROR);
+            break;
+        }
+        ... Do stuff ...
+        data += tlen;
+        len -= tlen;
+    }
+    ....
+}
+
+
+
+ +
+
+nghttp2_info *nghttp2_version(int least_version)¶
+

Returns a pointer to a nghttp2_info struct with version information about +the run-time library in use. The least_version argument can be set to a +24 bit numerical value for the least accepted version number and if the +condition is not met, this function will return a NULL. Pass in 0 to skip +the version checking.

+
+ +
+
+int nghttp2_is_fatal(int lib_error)¶
+

Returns nonzero if the nghttp2_error library error code +lib_error is fatal.

+
+ +
+
+int nghttp2_check_header_name(const uint8_t *name, size_t len)¶
+

Returns nonzero if HTTP header field name name of length len is +valid according to +http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-25#section-3.2

+

Because this is a header field name in HTTP2, the upper cased alphabet +is treated as error.

+
+ +
+
+int nghttp2_check_header_value(const uint8_t *value, size_t len)¶
+

Returns nonzero if HTTP header field value value of length len +is valid according to +http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-25#section-3.2

+

Because this is HTTP2 header field value, it can contain NULL +character (0x00).

+
+ +
+
+ + +
+ +
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/released-versions/v0.3.0/genindex.html b/released-versions/v0.3.0/genindex.html new file mode 100644 index 00000000..38e31963 --- /dev/null +++ b/released-versions/v0.3.0/genindex.html @@ -0,0 +1,1125 @@ + + + + + + + + + + + + + Index — nghttp2 0.3.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+
    +
  • Docs »
  • + +
  • +
  • + +
  • +
+
+
+
+ + +

Index

+ +
+ N + +
+

N

+ + + +
+ +
nghttp2_before_frame_send_callback (C type) +
+ + +
NGHTTP2_CANCEL (C macro) +
+ + +
nghttp2_check_header_name (C function) +
+ + +
nghttp2_check_header_value (C function) +
+ + +
NGHTTP2_CLIENT_CONNECTION_HEADER (C macro) +
+ + +
NGHTTP2_CLIENT_CONNECTION_HEADER_LEN (C macro) +
+ + +
NGHTTP2_COMPRESSION_ERROR (C macro) +
+ + +
NGHTTP2_CONNECT_ERROR (C macro) +
+ + +
NGHTTP2_CONTINUATION (C macro) +
+ + +
NGHTTP2_DATA (C macro) +
+ + +
nghttp2_data (C type) +
+ + +
nghttp2_data_provider (C type) +
+ + +
nghttp2_data_provider.read_callback (C member) +
+ + +
nghttp2_data_provider.source (C member) +
+ + +
nghttp2_data_source (C type) +
+ + +
nghttp2_data_source.fd (C member) +
+ + +
nghttp2_data_source.ptr (C member) +
+ + +
nghttp2_data_source_read_callback (C type) +
+ + +
NGHTTP2_ENHANCE_YOUR_CALM (C macro) +
+ + +
NGHTTP2_ERR_CALLBACK_FAILURE (C macro) +
+ + +
NGHTTP2_ERR_DEFERRED (C macro) +
+ + +
NGHTTP2_ERR_DEFERRED_DATA_EXIST (C macro) +
+ + +
NGHTTP2_ERR_EOF (C macro) +
+ + +
NGHTTP2_ERR_FATAL (C macro) +
+ + +
NGHTTP2_ERR_FLOW_CONTROL (C macro) +
+ + +
NGHTTP2_ERR_FRAME_SIZE_ERROR (C macro) +
+ + +
NGHTTP2_ERR_GOAWAY_ALREADY_SENT (C macro) +
+ + +
NGHTTP2_ERR_GZIP (C macro) +
+ + +
NGHTTP2_ERR_HEADER_COMP (C macro) +
+ + +
NGHTTP2_ERR_INSUFF_BUFSIZE (C macro) +
+ + +
NGHTTP2_ERR_INVALID_ARGUMENT (C macro) +
+ + +
NGHTTP2_ERR_INVALID_FRAME (C macro) +
+ + +
NGHTTP2_ERR_INVALID_HEADER_BLOCK (C macro) +
+ + +
NGHTTP2_ERR_INVALID_STATE (C macro) +
+ + +
NGHTTP2_ERR_INVALID_STREAM_ID (C macro) +
+ + +
NGHTTP2_ERR_INVALID_STREAM_STATE (C macro) +
+ + +
NGHTTP2_ERR_NOMEM (C macro) +
+ + +
NGHTTP2_ERR_PAUSE (C macro) +
+ + +
NGHTTP2_ERR_PROTO (C macro) +
+ + +
NGHTTP2_ERR_PUSH_DISABLED (C macro) +
+ + +
NGHTTP2_ERR_START_STREAM_NOT_ALLOWED (C macro) +
+ + +
NGHTTP2_ERR_STREAM_CLOSED (C macro) +
+ + +
NGHTTP2_ERR_STREAM_CLOSING (C macro) +
+ + +
NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE (C macro) +
+ + +
NGHTTP2_ERR_STREAM_SHUT_WR (C macro) +
+ + +
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE (C macro) +
+ + +
NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS (C macro) +
+ + +
NGHTTP2_ERR_UNSUPPORTED_VERSION (C macro) +
+ + +
NGHTTP2_ERR_WOULDBLOCK (C macro) +
+ + +
nghttp2_error (C type) +
+ + +
nghttp2_error_code (C type) +
+ + +
nghttp2_flag (C type) +
+ + +
NGHTTP2_FLAG_ACK (C macro) +
+ + +
NGHTTP2_FLAG_END_HEADERS (C macro) +
+ + +
NGHTTP2_FLAG_END_PUSH_PROMISE (C macro) +
+ + +
NGHTTP2_FLAG_END_STREAM (C macro) +
+ + +
NGHTTP2_FLAG_NONE (C macro) +
+ + +
NGHTTP2_FLAG_PRIORITY (C macro) +
+ + +
NGHTTP2_FLOW_CONTROL_ERROR (C macro) +
+ + +
nghttp2_frame (C type) +
+ + +
nghttp2_frame.data (C member) +
+ + +
nghttp2_frame.goaway (C member) +
+ + +
nghttp2_frame.hd (C member) +
+ + +
nghttp2_frame.headers (C member) +
+ + +
nghttp2_frame.ping (C member) +
+ + +
nghttp2_frame.priority (C member) +
+ + +
nghttp2_frame.push_promise (C member) +
+ + +
nghttp2_frame.rst_stream (C member) +
+ + +
nghttp2_frame.settings (C member) +
+ + +
nghttp2_frame.window_update (C member) +
+ + +
nghttp2_frame_hd (C type) +
+ + +
nghttp2_frame_hd.flags (C member) +
+ + +
nghttp2_frame_hd.length (C member) +
+ + +
nghttp2_frame_hd.stream_id (C member) +
+ + +
nghttp2_frame_hd.type (C member) +
+ + +
NGHTTP2_FRAME_SIZE_ERROR (C macro) +
+ + +
nghttp2_frame_type (C type) +
+ + +
NGHTTP2_GOAWAY (C macro) +
+ + +
nghttp2_goaway (C type) +
+ + +
nghttp2_goaway.error_code (C member) +
+ + +
nghttp2_goaway.hd (C member) +
+ + +
nghttp2_goaway.last_stream_id (C member) +
+ + +
nghttp2_goaway.opaque_data (C member) +
+ + +
nghttp2_goaway.opaque_data_len (C member) +
+ + +
nghttp2_gzip (C type) +
+ + +
nghttp2_gzip_inflate (C function) +
+ + +
nghttp2_gzip_inflate_del (C function) +
+ + +
nghttp2_gzip_inflate_new (C function) +
+ + +
NGHTTP2_HCAT_HEADERS (C macro) +
+ + +
NGHTTP2_HCAT_PUSH_RESPONSE (C macro) +
+ + +
NGHTTP2_HCAT_REQUEST (C macro) +
+ + +
NGHTTP2_HCAT_RESPONSE (C macro) +
+ + +
NGHTTP2_HEADERS (C macro) +
+ + +
nghttp2_headers (C type) +
+ + +
nghttp2_headers.cat (C member) +
+ + +
nghttp2_headers.hd (C member) +
+ + +
nghttp2_headers.nva (C member) +
+ + +
nghttp2_headers.nvlen (C member) +
+ + +
nghttp2_headers.pri (C member) +
+ + +
nghttp2_headers_category (C type) +
+ + +
nghttp2_info (C type) +
+ + +
nghttp2_info.age (C member) +
+ + +
nghttp2_info.proto_str (C member) +
+ + +
nghttp2_info.version_num (C member) +
+ + +
nghttp2_info.version_str (C member) +
+ + +
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE (C macro) +
+ + +
NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS (C macro) +
+ + +
NGHTTP2_INITIAL_WINDOW_SIZE (C macro) +
+ + +
NGHTTP2_INTERNAL_ERROR (C macro) +
+ + +
nghttp2_is_fatal (C function) +
+ + +
NGHTTP2_MAX_HEADER_TABLE_SIZE (C macro) +
+ + +
NGHTTP2_MAX_WINDOW_SIZE (C macro) +
+ + +
NGHTTP2_NO_ERROR (C macro) +
+ + +
nghttp2_nv (C type) +
+ + +
nghttp2_nv.name (C member) +
+ + +
nghttp2_nv.namelen (C member) +
+ + +
nghttp2_nv.value (C member) +
+ +
+ +
nghttp2_nv.valuelen (C member) +
+ + +
nghttp2_nv_compare_name (C function) +
+ + +
nghttp2_on_begin_headers_callback (C type) +
+ + +
nghttp2_on_data_chunk_recv_callback (C type) +
+ + +
nghttp2_on_frame_not_send_callback (C type) +
+ + +
nghttp2_on_frame_recv_callback (C type) +
+ + +
nghttp2_on_frame_send_callback (C type) +
+ + +
nghttp2_on_header_callback (C type) +
+ + +
nghttp2_on_invalid_frame_recv_callback (C type) +
+ + +
nghttp2_on_stream_close_callback (C type) +
+ + +
nghttp2_on_unknown_frame_recv_callback (C type) +
+ + +
nghttp2_opt (C type) +
+ + +
NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE (C macro) +
+ + +
NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE (C macro) +
+ + +
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS (C macro) +
+ + +
nghttp2_opt_set (C type) +
+ + +
nghttp2_opt_set.no_auto_connection_window_update (C member) +
+ + +
nghttp2_opt_set.no_auto_stream_window_update (C member) +
+ + +
nghttp2_opt_set.peer_max_concurrent_streams (C member) +
+ + +
nghttp2_pack_settings_payload (C function) +
+ + +
NGHTTP2_PING (C macro) +
+ + +
nghttp2_ping (C type) +
+ + +
nghttp2_ping.hd (C member) +
+ + +
NGHTTP2_PRI_DEFAULT (C macro) +
+ + +
NGHTTP2_PRI_LOWEST (C macro) +
+ + +
NGHTTP2_PRIORITY (C macro) +
+ + +
nghttp2_priority (C type) +
+ + +
nghttp2_priority.hd (C member) +
+ + +
nghttp2_priority.pri (C member) +
+ + +
NGHTTP2_PROTO_VERSION_ID (C macro) +
+ + +
NGHTTP2_PROTO_VERSION_ID_LEN (C macro) +
+ + +
NGHTTP2_PROTOCOL_ERROR (C macro) +
+ + +
NGHTTP2_PUSH_PROMISE (C macro) +
+ + +
nghttp2_push_promise (C type) +
+ + +
nghttp2_push_promise.hd (C member) +
+ + +
nghttp2_push_promise.nva (C member) +
+ + +
nghttp2_push_promise.nvlen (C member) +
+ + +
nghttp2_push_promise.promised_stream_id (C member) +
+ + +
nghttp2_recv_callback (C type) +
+ + +
NGHTTP2_REFUSED_STREAM (C macro) +
+ + +
NGHTTP2_RST_STREAM (C macro) +
+ + +
nghttp2_rst_stream (C type) +
+ + +
nghttp2_rst_stream.error_code (C member) +
+ + +
nghttp2_rst_stream.hd (C member) +
+ + +
nghttp2_select_next_protocol (C function) +
+ + +
nghttp2_send_callback (C type) +
+ + +
nghttp2_session (C type) +
+ + +
nghttp2_session_callbacks (C type) +
+ + +
nghttp2_session_callbacks.before_frame_send_callback (C member) +
+ + +
nghttp2_session_callbacks.on_begin_headers_callback (C member) +
+ + +
nghttp2_session_callbacks.on_data_chunk_recv_callback (C member) +
+ + +
nghttp2_session_callbacks.on_frame_not_send_callback (C member) +
+ + +
nghttp2_session_callbacks.on_frame_recv_callback (C member) +
+ + +
nghttp2_session_callbacks.on_frame_send_callback (C member) +
+ + +
nghttp2_session_callbacks.on_header_callback (C member) +
+ + +
nghttp2_session_callbacks.on_invalid_frame_recv_callback (C member) +
+ + +
nghttp2_session_callbacks.on_stream_close_callback (C member) +
+ + +
nghttp2_session_callbacks.on_unknown_frame_recv_callback (C member) +
+ + +
nghttp2_session_callbacks.recv_callback (C member) +
+ + +
nghttp2_session_callbacks.send_callback (C member) +
+ + +
nghttp2_session_client_new (C function) +
+ + +
nghttp2_session_client_new2 (C function) +
+ + +
nghttp2_session_del (C function) +
+ + +
nghttp2_session_get_effective_local_window_size (C function) +
+ + +
nghttp2_session_get_effective_recv_data_length (C function) +
+ + +
nghttp2_session_get_outbound_queue_size (C function) +
+ + +
nghttp2_session_get_stream_effective_local_window_size (C function) +
+ + +
nghttp2_session_get_stream_effective_recv_data_length (C function) +
+ + +
nghttp2_session_get_stream_user_data (C function) +
+ + +
nghttp2_session_mem_recv (C function) +
+ + +
nghttp2_session_recv (C function) +
+ + +
nghttp2_session_resume_data (C function) +
+ + +
nghttp2_session_send (C function) +
+ + +
nghttp2_session_server_new (C function) +
+ + +
nghttp2_session_server_new2 (C function) +
+ + +
nghttp2_session_set_stream_user_data (C function) +
+ + +
nghttp2_session_terminate_session (C function) +
+ + +
nghttp2_session_upgrade (C function) +
+ + +
nghttp2_session_want_read (C function) +
+ + +
nghttp2_session_want_write (C function) +
+ + +
NGHTTP2_SETTINGS (C macro) +
+ + +
nghttp2_settings (C type) +
+ + +
nghttp2_settings.hd (C member) +
+ + +
nghttp2_settings.iv (C member) +
+ + +
nghttp2_settings.niv (C member) +
+ + +
NGHTTP2_SETTINGS_ENABLE_PUSH (C macro) +
+ + +
nghttp2_settings_entry (C type) +
+ + +
nghttp2_settings_entry.settings_id (C member) +
+ + +
nghttp2_settings_entry.value (C member) +
+ + +
NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS (C macro) +
+ + +
NGHTTP2_SETTINGS_HEADER_TABLE_SIZE (C macro) +
+ + +
nghttp2_settings_id (C type) +
+ + +
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE (C macro) +
+ + +
NGHTTP2_SETTINGS_MAX (C macro) +
+ + +
NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS (C macro) +
+ + +
NGHTTP2_SETTINGS_TIMEOUT (C macro) +
+ + +
NGHTTP2_STREAM_CLOSED (C macro) +
+ + +
nghttp2_strerror (C function) +
+ + +
nghttp2_submit_data (C function) +
+ + +
nghttp2_submit_goaway (C function) +
+ + +
nghttp2_submit_headers (C function) +
+ + +
nghttp2_submit_ping (C function) +
+ + +
nghttp2_submit_priority (C function) +
+ + +
nghttp2_submit_push_promise (C function) +
+ + +
nghttp2_submit_request (C function) +
+ + +
nghttp2_submit_response (C function) +
+ + +
nghttp2_submit_rst_stream (C function) +
+ + +
nghttp2_submit_settings (C function) +
+ + +
nghttp2_submit_window_update (C function) +
+ + +
nghttp2_version (C function) +
+ + +
NGHTTP2_VERSION (C macro) +
+ + +
NGHTTP2_VERSION_AGE (C macro) +
+ + +
NGHTTP2_VERSION_NUM (C macro) +
+ + +
NGHTTP2_WINDOW_UPDATE (C macro) +
+ + +
nghttp2_window_update (C type) +
+ + +
nghttp2_window_update.hd (C member) +
+ + +
nghttp2_window_update.window_size_increment (C member) +
+ +
+ + + +
+ +
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/released-versions/v0.3.0/index.html b/released-versions/v0.3.0/index.html new file mode 100644 index 00000000..dd02de5f --- /dev/null +++ b/released-versions/v0.3.0/index.html @@ -0,0 +1,239 @@ + + + + + + + + + + + nghttp2 - HTTP/2.0 C Library — nghttp2 0.3.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+ + + + + +
+ +
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/released-versions/v0.3.0/nghttp2.h.html b/released-versions/v0.3.0/nghttp2.h.html new file mode 100644 index 00000000..44114d1a --- /dev/null +++ b/released-versions/v0.3.0/nghttp2.h.html @@ -0,0 +1,2548 @@ + + + + + + + + + + + nghttp2.h — nghttp2 0.3.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+ +
+

nghttp2.h¶

+
/*
+ * nghttp2 - HTTP/2.0 C Library
+ *
+ * Copyright (c) 2013, 2014 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.
+ */
+#ifndef NGHTTP2_H
+#define NGHTTP2_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <nghttp2/nghttp2ver.h>
+
+/**
+ * @macro
+ *
+ * The protocol version identification of this library supports.
+ */
+#define NGHTTP2_PROTO_VERSION_ID "HTTP-draft-09/2.0"
+/**
+ * @macro
+ *
+ * The length of :macro:`NGHTTP2_PROTO_VERSION_ID`.
+ */
+#define NGHTTP2_PROTO_VERSION_ID_LEN 17
+
+struct nghttp2_session;
+/**
+ * @struct
+ *
+ * The primary structure to hold the resources needed for a HTTP/2.0
+ * session. The details of this structure are intentionally hidden
+ * from the public API.
+ */
+typedef struct nghttp2_session nghttp2_session;
+
+/**
+ * @macro
+ *
+ * The age of :type:`nghttp2_info`
+ */
+#define NGHTTP2_VERSION_AGE 1
+
+/**
+ * @struct
+ *
+ * This struct is what `nghttp2_version()` returns. It holds
+ * information about the particular nghttp2 version.
+ */
+typedef struct {
+  /**
+   * Age of this struct. This instance of nghttp2 sets it to
+   * :macro:`NGHTTP2_VERSION_AGE` but a future version may bump it and
+   * add more struct fields at the bottom
+   */
+  int age;
+  /**
+   * the :macro:`NGHTTP2_VERSION_NUM` number (since age ==1)
+   */
+  int version_num;
+  /**
+   * points to the :macro:`NGHTTP2_VERSION` string (since age ==1)
+   */
+  const char *version_str;
+  /**
+   * points to the :macro:`NGHTTP2_PROTO_VERSION_ID` string this
+   * instance implements (since age ==1)
+   */
+  const char *proto_str;
+  /* -------- the above fields all exist when age == 1 */
+} nghttp2_info;
+
+/**
+ * @macro
+ *
+ * The default priority value
+ */
+#define NGHTTP2_PRI_DEFAULT (1 << 30)
+/**
+ * @macro
+ *
+ * The lowest priority value
+ */
+#define NGHTTP2_PRI_LOWEST ((1U << 31) - 1)
+
+/**
+ * @macro
+ *
+ * The maximum window size
+ */
+#define NGHTTP2_MAX_WINDOW_SIZE ((int32_t)((1U << 31) - 1))
+
+/**
+ * @macro
+ *
+ * The initial window size for stream level flow control.
+ */
+#define NGHTTP2_INITIAL_WINDOW_SIZE ((1 << 16) - 1)
+/**
+ * @macro
+ *
+ * The initial window size for connection level flow control.
+ */
+#define NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ((1 << 16) - 1)
+
+/**
+ * @macro
+ *
+ * The maximum header table size.
+ */
+#define NGHTTP2_MAX_HEADER_TABLE_SIZE (1 << 16)
+
+/**
+ * @macro
+ *
+ * The client connection header.
+ */
+#define NGHTTP2_CLIENT_CONNECTION_HEADER "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+/**
+ * @macro
+ *
+ * The length of :macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`.
+ */
+#define NGHTTP2_CLIENT_CONNECTION_HEADER_LEN 24
+
+/**
+ * @enum
+ *
+ * Error codes used in this library. The code range is [-999, -500],
+ * inclusive. The following values are defined:
+ */
+typedef enum {
+  /**
+   * Invalid argument passed.
+   */
+  NGHTTP2_ERR_INVALID_ARGUMENT = -501,
+  /**
+   * The specified protocol version is not supported.
+   */
+  NGHTTP2_ERR_UNSUPPORTED_VERSION = -503,
+  /**
+   * Used as a return value from :type:`nghttp2_send_callback` and
+   * :type:`nghttp2_recv_callback` to indicate that the operation
+   * would block.
+   */
+  NGHTTP2_ERR_WOULDBLOCK = -504,
+  /**
+   * General protocol error
+   */
+  NGHTTP2_ERR_PROTO = -505,
+  /**
+   * The frame is invalid.
+   */
+  NGHTTP2_ERR_INVALID_FRAME = -506,
+  /**
+   * The peer performed a shutdown on the connection.
+   */
+  NGHTTP2_ERR_EOF = -507,
+  /**
+   * Used as a return value from
+   * :func:`nghttp2_data_source_read_callback` to indicate that data
+   * transfer is postponed. See
+   * :func:`nghttp2_data_source_read_callback` for details.
+   */
+  NGHTTP2_ERR_DEFERRED = -508,
+  /**
+   * Stream ID has reached the maximum value. Therefore no stream ID
+   * is available.
+   */
+  NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE = -509,
+  /**
+   * The stream is already closed; or the stream ID is invalid.
+   */
+  NGHTTP2_ERR_STREAM_CLOSED = -510,
+  /**
+   * RST_STREAM has been added to the outbound queue. The stream is in
+   * closing state.
+   */
+  NGHTTP2_ERR_STREAM_CLOSING = -511,
+  /**
+   * The transmission is not allowed for this stream (e.g., a frame
+   * with END_STREAM flag set has already sent).
+   */
+  NGHTTP2_ERR_STREAM_SHUT_WR = -512,
+  /**
+   * The stream ID is invalid.
+   */
+  NGHTTP2_ERR_INVALID_STREAM_ID = -513,
+  /**
+   * The state of the stream is not valid (e.g., DATA cannot be sent
+   * to the stream if response HEADERS has not been sent).
+   */
+  NGHTTP2_ERR_INVALID_STREAM_STATE = -514,
+  /**
+   * Another DATA frame has already been deferred.
+   */
+  NGHTTP2_ERR_DEFERRED_DATA_EXIST = -515,
+  /**
+   * Starting new stream is not allowed. (e.g., GOAWAY has been sent
+   * and/or received.
+   */
+  NGHTTP2_ERR_START_STREAM_NOT_ALLOWED = -516,
+  /**
+   * GOAWAY has already been sent.
+   */
+  NGHTTP2_ERR_GOAWAY_ALREADY_SENT = -517,
+  /**
+   * The received frame contains the invalid header block. (e.g.,
+   * There are duplicate header names; or the header names are not
+   * encoded in US-ASCII character set and not lower cased; or the
+   * header name is zero-length string; or the header value contains
+   * multiple in-sequence NUL bytes).
+   */
+  NGHTTP2_ERR_INVALID_HEADER_BLOCK = -518,
+  /**
+   * Indicates that the context is not suitable to perform the
+   * requested operation.
+   */
+  NGHTTP2_ERR_INVALID_STATE = -519,
+  /**
+   * The gzip error.
+   */
+  NGHTTP2_ERR_GZIP = -520,
+  /**
+   * The user callback function failed due to the temporal error.
+   */
+  NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE = -521,
+  /**
+   * The length of the frame is invalid, either too large or too small.
+   */
+  NGHTTP2_ERR_FRAME_SIZE_ERROR = -522,
+  /**
+   * Header block inflate/deflate error.
+   */
+  NGHTTP2_ERR_HEADER_COMP = -523,
+  /**
+   * Flow control error
+   */
+  NGHTTP2_ERR_FLOW_CONTROL = -524,
+  /**
+   * Insufficient buffer size given to function.
+   */
+  NGHTTP2_ERR_INSUFF_BUFSIZE = -525,
+  /**
+   * Callback was paused by the application
+   */
+  NGHTTP2_ERR_PAUSE = -526,
+  /**
+   * There are too many in-flight SETTING frame and no more
+   * transmission of SETTINGS is allowed.
+   */
+  NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS = -527,
+  /**
+   * The server push is disabled.
+   */
+  NGHTTP2_ERR_PUSH_DISABLED = -528,
+  /**
+   * The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
+   * under unexpected condition and cannot process any further data
+   * reliably (e.g., out of memory).
+   */
+  NGHTTP2_ERR_FATAL = -900,
+  /**
+   * Out of memory. This is a fatal error.
+   */
+  NGHTTP2_ERR_NOMEM = -901,
+  /**
+   * The user callback function failed. This is a fatal error.
+   */
+  NGHTTP2_ERR_CALLBACK_FAILURE = -902
+} nghttp2_error;
+
+typedef enum {
+  NGHTTP2_MSG_MORE
+} nghttp2_io_flag;
+
+/**
+ * @struct
+ *
+ * The name/value pair, which mainly used to represent header fields.
+ */
+typedef struct {
+  /**
+   * The |name| byte string, which is not necessarily ``NULL``
+   * terminated.
+   */
+  uint8_t *name;
+  /**
+   * The |value| byte string, which is not necessarily ``NULL``
+   * terminated.
+   */
+  uint8_t *value;
+  /**
+   * The length of the |name|.
+   */
+  uint16_t namelen;
+  /**
+   * The length of the |value|.
+   */
+  uint16_t valuelen;
+} nghttp2_nv;
+
+/**
+ * @enum
+ * The control frame types in HTTP/2.0.
+ */
+typedef enum {
+  /**
+   * The DATA frame.
+   */
+  NGHTTP2_DATA = 0,
+  /**
+   * The HEADERS frame.
+   */
+  NGHTTP2_HEADERS = 1,
+  /**
+   * The PRIORITY frame.
+   */
+  NGHTTP2_PRIORITY = 2,
+  /**
+   * The RST_STREAM frame.
+   */
+  NGHTTP2_RST_STREAM = 3,
+  /**
+   * The SETTINGS frame.
+   */
+  NGHTTP2_SETTINGS = 4,
+  /**
+   * The PUSH_PROMISE frame.
+   */
+  NGHTTP2_PUSH_PROMISE = 5,
+  /**
+   * The PING frame.
+   */
+  NGHTTP2_PING = 6,
+  /**
+   * The GOAWAY frame.
+   */
+  NGHTTP2_GOAWAY = 7,
+  /**
+   * The WINDOW_UPDATE frame.
+   */
+  NGHTTP2_WINDOW_UPDATE = 9,
+  /**
+   * The CONTINUATION frame.
+   */
+  NGHTTP2_CONTINUATION = 10
+} nghttp2_frame_type;
+
+/**
+ * @enum
+ *
+ * The flags for HTTP/2.0 frames. This enum defines all flags for
+ * frames, assuming that the same flag name has the same mask.
+ */
+typedef enum {
+  /**
+   * No flag set.
+   */
+  NGHTTP2_FLAG_NONE = 0,
+  /**
+   * The END_STREAM flag.
+   */
+  NGHTTP2_FLAG_END_STREAM = 0x1,
+  /**
+   * The END_HEADERS flag.
+   */
+  NGHTTP2_FLAG_END_HEADERS = 0x4,
+  /**
+   * The PRIORITY flag.
+   */
+  NGHTTP2_FLAG_PRIORITY = 0x8,
+  /**
+   * The END_PUSH_PROMISE flag.
+   */
+  NGHTTP2_FLAG_END_PUSH_PROMISE = 0x4,
+  /**
+   * The ACK flag.
+   */
+  NGHTTP2_FLAG_ACK = 0x1
+} nghttp2_flag;
+
+/**
+ * @enum
+ * The SETTINGS ID.
+ */
+typedef enum {
+  /**
+   * SETTINGS_HEADER_TABLE_SIZE
+   */
+  NGHTTP2_SETTINGS_HEADER_TABLE_SIZE = 1,
+  /**
+   * SETTINGS_ENABLE_PUSH
+   */
+  NGHTTP2_SETTINGS_ENABLE_PUSH = 2,
+  /**
+   * SETTINGS_MAX_CONCURRENT_STREAMS
+   */
+  NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 4,
+  /**
+   * SETTINGS_INITIAL_WINDOW_SIZE
+   */
+  NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 7,
+  /**
+   * SETTINGS_FLOW_CONTROL_OPTIONS
+   */
+  NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS = 10,
+  /**
+   * Maximum ID of :type:`nghttp2_settings_id`.
+   */
+  NGHTTP2_SETTINGS_MAX = 10
+} nghttp2_settings_id;
+
+/**
+ * @macro
+ * Default maximum concurrent streams.
+ */
+#define NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)
+
+/**
+ * @enum
+ * The status codes for the RST_STREAM and GOAWAY frames.
+ */
+typedef enum {
+  /**
+   * No errors.
+   */
+  NGHTTP2_NO_ERROR = 0,
+  /**
+   * PROTOCOL_ERROR
+   */
+  NGHTTP2_PROTOCOL_ERROR = 1,
+  /**
+   * INTERNAL_ERROR
+   */
+  NGHTTP2_INTERNAL_ERROR = 2,
+  /**
+   * FLOW_CONTROL_ERROR
+   */
+  NGHTTP2_FLOW_CONTROL_ERROR = 3,
+  /**
+   * SETTINGS_TIMEOUT
+   */
+  NGHTTP2_SETTINGS_TIMEOUT = 4,
+  /**
+   * STREAM_CLOSED
+   */
+  NGHTTP2_STREAM_CLOSED = 5,
+  /**
+   * FRAME_SIZE_ERROR
+   */
+  NGHTTP2_FRAME_SIZE_ERROR = 6,
+  /**
+   * REFUSED_STREAM
+   */
+  NGHTTP2_REFUSED_STREAM = 7,
+  /**
+   * CANCEL
+   */
+  NGHTTP2_CANCEL = 8,
+  /**
+   * COMPRESSION_ERROR
+   */
+  NGHTTP2_COMPRESSION_ERROR = 9,
+  /**
+   * CONNECT_ERROR
+   */
+  NGHTTP2_CONNECT_ERROR = 10,
+  /**
+   * ENHANCE_YOUR_CALM
+   */
+  NGHTTP2_ENHANCE_YOUR_CALM = 420
+} nghttp2_error_code;
+
+/**
+ * @struct
+ * The frame header.
+ */
+typedef struct {
+  /**
+   * The length field of this frame, excluding frame header.
+   */
+  size_t length;
+  /**
+   * The stream identifier (aka, stream ID)
+   */
+  int32_t stream_id;
+  /**
+   * The type of this frame. See `nghttp2_frame`.
+   */
+  uint8_t type;
+  /**
+   * The flags.
+   */
+  uint8_t flags;
+} nghttp2_frame_hd;
+
+
+/**
+ * @union
+ *
+ * This union represents the some kind of data source passed to
+ * :type:`nghttp2_data_source_read_callback`.
+ */
+typedef union {
+  /**
+   * The integer field, suitable for a file descriptor.
+   */
+  int fd;
+  /**
+   * The pointer to an arbitrary object.
+   */
+  void *ptr;
+} nghttp2_data_source;
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the library wants to read data from
+ * the |source|. The read data is sent in the stream |stream_id|. The
+ * implementation of this function must read at most |length| bytes of
+ * data from |source| (or possibly other places) and store them in
+ * |buf| and return number of data stored in |buf|. If EOF is reached,
+ * set |*eof| to 1.  If the application wants to postpone DATA frames,
+ * (e.g., asynchronous I/O, or reading data blocks for long time), it
+ * is achieved by returning :enum:`NGHTTP2_ERR_DEFERRED` without
+ * reading any data in this invocation.  The library removes DATA
+ * frame from the outgoing queue temporarily.  To move back deferred
+ * DATA frame to outgoing queue, call `nghttp2_session_resume_data()`.
+ * In case of error, there are 2 choices. Returning
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close the stream
+ * by issuing RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`.
+ * Returning :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the
+ * entire session failure.
+ */
+typedef ssize_t (*nghttp2_data_source_read_callback)
+(nghttp2_session *session, int32_t stream_id,
+ uint8_t *buf, size_t length, int *eof,
+ nghttp2_data_source *source, void *user_data);
+
+/**
+ * @struct
+ *
+ * This struct represents the data source and the way to read a chunk
+ * of data from it.
+ */
+typedef struct {
+  /**
+   * The data source.
+   */
+  nghttp2_data_source source;
+  /**
+   * The callback function to read a chunk of data from the |source|.
+   */
+  nghttp2_data_source_read_callback read_callback;
+} nghttp2_data_provider;
+
+/**
+ * @struct
+ *
+ * The DATA frame. The received data is delivered via
+ * :type:`nghttp2_on_data_chunk_recv_callback`.
+ */
+typedef struct {
+  nghttp2_frame_hd hd;
+} nghttp2_data;
+
+/**
+ * @enum
+ *
+ * The category of HEADERS, which indicates the role of the frame. In
+ * HTTP/2.0 spec, request, response, push response and other arbitrary
+ * headers (e.g., trailers) are all called just HEADERS. To give the
+ * application the role of incoming HEADERS frame, we define several
+ * categories.
+ */
+typedef enum {
+  /**
+   * The HEADERS frame is opening new stream, which is analogous to
+   * SYN_STREAM in SPDY.
+   */
+  NGHTTP2_HCAT_REQUEST = 0,
+  /**
+   * The HEADERS frame is the first response headers, which is
+   * analogous to SYN_REPLY in SPDY.
+   */
+  NGHTTP2_HCAT_RESPONSE = 1,
+  /**
+   * The HEADERS frame is the first headers sent against reserved
+   * stream.
+   */
+  NGHTTP2_HCAT_PUSH_RESPONSE = 2,
+  /**
+   * The HEADERS frame which does not apply for the above categories,
+   * which is analogous to HEADERS in SPDY.
+   */
+  NGHTTP2_HCAT_HEADERS = 3
+} nghttp2_headers_category;
+
+/**
+ * @struct
+ * The HEADERS frame. It has the following members:
+ */
+typedef struct {
+  /**
+   * The frame header.
+   */
+  nghttp2_frame_hd hd;
+  /**
+   * The name/value pairs.
+   */
+  nghttp2_nv *nva;
+  /**
+   * The number of name/value pairs in |nva|.
+   */
+  size_t nvlen;
+  /**
+   * The category of this HEADERS frame.
+   */
+  nghttp2_headers_category cat;
+  /**
+   * The priority.
+   */
+  int32_t pri;
+} nghttp2_headers;
+
+/**
+ * @struct
+ * The PRIORITY frame. It has the following members:
+ */
+typedef struct {
+  /**
+   * The frame header.
+   */
+  nghttp2_frame_hd hd;
+  /**
+   * The priority.
+   */
+  int32_t pri;
+} nghttp2_priority;
+
+/**
+ * @struct
+ * The RST_STREAM frame. It has the following members:
+ */
+typedef struct {
+  /**
+   * The frame header.
+   */
+  nghttp2_frame_hd hd;
+  /**
+   * The error code. See :type:`nghttp2_error_code`.
+   */
+  nghttp2_error_code error_code;
+} nghttp2_rst_stream;
+
+/**
+ * @struct
+ * The SETTINGS ID/Value pair. It has the following members:
+ */
+typedef struct {
+  /**
+   * The SETTINGS ID. See :type:`nghttp2_settings_id`.
+   */
+  int32_t settings_id;
+  /**
+   * The value of this entry.
+   */
+  uint32_t value;
+} nghttp2_settings_entry;
+
+/**
+ * @struct
+ * The SETTINGS frame. It has the following members:
+ */
+typedef struct {
+  /**
+   * The frame header.
+   */
+  nghttp2_frame_hd hd;
+  /**
+   * The number of SETTINGS ID/Value pairs in |iv|.
+   */
+  size_t niv;
+  /**
+   * The pointer to the array of SETTINGS ID/Value pair.
+   */
+  nghttp2_settings_entry *iv;
+} nghttp2_settings;
+
+/**
+ * @struct
+ * The PUSH_PROMISE frame. It has the following members:
+ */
+typedef struct {
+  /**
+   * The frame header.
+   */
+  nghttp2_frame_hd hd;
+  /**
+   * The name/value pairs.
+   */
+  nghttp2_nv *nva;
+  /**
+   * The number of name/value pairs in |nva|.
+   */
+  size_t nvlen;
+  /**
+   * The promised stream ID
+   */
+  int32_t promised_stream_id;
+} nghttp2_push_promise;
+
+/**
+ * @struct
+ * The PING frame. It has the following members:
+ */
+typedef struct {
+  /**
+   * The frame header.
+   */
+  nghttp2_frame_hd hd;
+  /**
+   * The opaque data
+   */
+  uint8_t opaque_data[8];
+} nghttp2_ping;
+
+/**
+ * @struct
+ * The GOAWAY frame. It has the following members:
+ */
+typedef struct {
+  /**
+   * The frame header.
+   */
+  nghttp2_frame_hd hd;
+  /**
+   * The last stream stream ID.
+   */
+  int32_t last_stream_id;
+  /**
+   * The error code. See :type:`nghttp2_error_code`.
+   */
+  nghttp2_error_code error_code;
+  /**
+   * The additional debug data
+   */
+  uint8_t *opaque_data;
+  /**
+   * The length of |opaque_data| member.
+   */
+  size_t opaque_data_len;
+} nghttp2_goaway;
+
+/**
+ * @struct
+ *
+ * The WINDOW_UPDATE frame. It has the following members:
+ */
+typedef struct {
+  /**
+   * The frame header.
+   */
+  nghttp2_frame_hd hd;
+  /**
+   * The window size increment.
+   */
+  int32_t window_size_increment;
+} nghttp2_window_update;
+
+/**
+ * @union
+ *
+ * This union includes all frames to pass them to various function
+ * calls as nghttp2_frame type. The CONTINUATION frame is omitted from
+ * here because the library deals with it internally.
+ */
+typedef union {
+  /**
+   * The frame header, which is convenient to inspect frame header.
+   */
+  nghttp2_frame_hd hd;
+  /**
+   * The DATA frame.
+   */
+  nghttp2_data data;
+  /**
+   * The HEADERS frame.
+   */
+  nghttp2_headers headers;
+  /**
+   * The PRIORITY frame.
+   */
+  nghttp2_priority priority;
+  /**
+   * The RST_STREAM frame.
+   */
+  nghttp2_rst_stream rst_stream;
+  /**
+   * The SETTINGS frame.
+   */
+  nghttp2_settings settings;
+  /**
+   * The PUSH_PROMISE frame.
+   */
+  nghttp2_push_promise push_promise;
+  /**
+   * The PING frame.
+   */
+  nghttp2_ping ping;
+  /**
+   * The GOAWAY frame.
+   */
+  nghttp2_goaway goaway;
+  /**
+   * The WINDOW_UPDATE frame.
+   */
+  nghttp2_window_update window_update;
+} nghttp2_frame;
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when |session| wants to send data to the
+ * remote peer. The implementation of this function must send at most
+ * |length| bytes of data stored in |data|. The |flags| is currently
+ * not used and always 0. It must return the number of bytes sent if
+ * it succeeds.  If it cannot send any single byte without blocking,
+ * it must return :enum:`NGHTTP2_ERR_WOULDBLOCK`. For other errors, it
+ * must return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. The |user_data|
+ * pointer is the third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ */
+typedef ssize_t (*nghttp2_send_callback)
+(nghttp2_session *session,
+ const uint8_t *data, size_t length, int flags, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when |session| wants to receive data from
+ * the remote peer. The implementation of this function must read at
+ * most |length| bytes of data and store it in |buf|. The |flags| is
+ * currently not used and always 0. It must return the number of bytes
+ * written in |buf| if it succeeds. If it cannot read any single byte
+ * without blocking, it must return :enum:`NGHTTP2_ERR_WOULDBLOCK`. If
+ * it gets EOF before it reads any single byte, it must return
+ * :enum:`NGHTTP2_ERR_EOF`. For other errors, it must return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Returning 0 is treated as
+ * :enum:`NGHTTP2_ERR_WOULDBLOCK`. The |user_data| pointer is the
+ * third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ */
+typedef ssize_t (*nghttp2_recv_callback)
+(nghttp2_session *session,
+ uint8_t *buf, size_t length, int flags, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked by `nghttp2_session_recv()` when a aframe
+ * is received. The |user_data| pointer is the third argument passed
+ * in to the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen``
+ * member of their data structure are always ``NULL`` and 0
+ * respectively. The header name/value pairs are emitted via
+ * :type:`nghttp2_on_header_callback`.
+ *
+ * For HEADERS, PUSH_PROMISE and DATA frames, this callback may be
+ * called after stream is closed (see
+ * :type:`nghttp2_on_stream_close_callback`). The application should
+ * check that stream is still alive using its own stream management or
+ * :func:`nghttp2_session_get_stream_user_data()`.
+ *
+ * Only HEADERS and DATA frame can signal the end of incoming data. If
+ * ``frame->hd.flags & NGHTTP2_FLAG_END_STREAM`` is nonzero, the
+ * |frame| is the last frame from the remote peer in this stream.
+ *
+ * The implementation of this function must return 0 if it
+ * succeeds. If nonzero value is returned, it is treated as fatal
+ * error and `nghttp2_session_recv()` and `nghttp2_session_mem_recv()`
+ * functions immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_frame_recv_callback)
+(nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked by `nghttp2_session_recv()` when an
+ * invalid non-DATA frame is received. The |error_code| is one of the
+ * :enum:`nghttp2_error_code` and indicates the error. When this
+ * callback function is invoked, the library automatically submits
+ * either RST_STREAM or GOAWAY frame. The |user_data| pointer is the
+ * third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen``
+ * member of their data structure are always ``NULL`` and 0
+ * respectively.
+ *
+ * The implementation of this function must return 0 if it
+ * succeeds. If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_invalid_frame_recv_callback)
+(nghttp2_session *session, const nghttp2_frame *frame,
+ nghttp2_error_code error_code, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a chunk of data in DATA frame is
+ * received. The |stream_id| is the stream ID this DATA frame belongs
+ * to. The |flags| is the flags of DATA frame which this data chunk is
+ * contained. ``(flags & NGHTTP2_FLAG_END_STREAM) != 0`` does not
+ * necessarily mean this chunk of data is the last one in the
+ * stream. You should use :type:`nghttp2_on_frame_recv_callback` to
+ * know all data frames are received. The |user_data| pointer is the
+ * third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * If the application uses `nghttp2_session_mem_recv()`, it can return
+ * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`
+ * return without processing further input bytes.  The memory by
+ * pointed by the |data| is retained until
+ * `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is
+ * called. The application must retain the input bytes which was used
+ * to produce the |data| parameter, because it may refer to the memory
+ * region included in the input bytes.
+ *
+ * The implementation of this function must return 0 if it
+ * succeeds. If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_data_chunk_recv_callback)
+(nghttp2_session *session, uint8_t flags, int32_t stream_id,
+ const uint8_t *data, size_t len, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked before the non-DATA frame |frame| is
+ * sent. This may be useful, for example, to know the stream ID of
+ * HEADERS and PUSH_PROMISE frame (see also
+ * `nghttp2_session_get_stream_user_data()`), which is not assigned
+ * when it was queued. The |user_data| pointer is the third argument
+ * passed in to the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * The implementation of this function must return 0 if it
+ * succeeds. If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_before_frame_send_callback)
+(nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked after the frame |frame| is sent.  The
+ * |user_data| pointer is the third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * The implementation of this function must return 0 if it
+ * succeeds. If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_frame_send_callback)
+(nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked after the non-DATA frame |frame| is not
+ * sent because of the error. The error is indicated by the
+ * |lib_error_code|, which is one of the values defined in
+ * :type:`nghttp2_error`. The |user_data| pointer is the third
+ * argument passed in to the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * The implementation of this function must return 0 if it
+ * succeeds. If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_frame_not_send_callback)
+(nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the stream |stream_id| is
+ * closed. The reason of closure is indicated by the |error_code|. The
+ * stream_user_data, which was specified in `nghttp2_submit_request()`
+ * or `nghttp2_submit_headers()`, is still available in this
+ * function. The |user_data| pointer is the third argument passed in
+ * to the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * The implementation of this function must return 0 if it
+ * succeeds. If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_stream_close_callback)
+(nghttp2_session *session, int32_t stream_id, nghttp2_error_code error_code,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the received frame type is
+ * unknown. The |head| is the pointer to the header of the received
+ * frame. The |headlen| is the length of the |head|. According to the
+ * spec, the |headlen| is always 8. In other words, the |head| is the
+ * first 8 bytes of the received frame.  The |payload| is the pointer
+ * to the data portion of the received frame.  The |payloadlen| is the
+ * length of the |payload|. This is the data after the length
+ * field. The |user_data| pointer is the third argument passed in to
+ * the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * The implementation of this function must return 0 if it
+ * succeeds. If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_unknown_frame_recv_callback)
+(nghttp2_session *session,
+ const uint8_t *head, size_t headlen,
+ const uint8_t *payload, size_t payloadlen,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the reception of header block in
+ * HEADERS or PUSH_PROMISE is started. Each header name/value pair
+ * will be emitted by :type:`nghttp2_on_header_callback`.
+ *
+ * The ``frame->hd.flags`` may not have
+ * :enum:`NGHTTP2_FLAG_END_HEADERS` flag set, which indicates that one
+ * or more CONTINUATION frames are involved. But the application does
+ * not need to care about that because the header name/value pairs are
+ * emitted transparently regardless of CONTINUATION frames.
+ *
+ * The implementation of this function must return 0 if it succeeds or
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If nonzero value other than
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, it is treated as
+ * if :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. If
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned,
+ * `nghttp2_session_mem_recv()` function will immediately return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_begin_headers_callback)
+(nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a header name/value pair is received
+ * for the |frame|. When this callback is invoked, ``frame->hd.type``
+ * is either :enum:`NGHTTP2_HEADERS` or :enum:`NGHTTP2_PUSH_PROMISE`.
+ * After all header name/value pairs are processed with this callback,
+ * and no error has been detected,
+ * :type:`nghttp2_on_frame_recv_callback` will be invoked.  If there
+ * is an error in decompression,
+ * :type:`nghttp2_on_frame_recv_callback` for the |frame| will not be
+ * invoked.
+ *
+ * The |name| may be ``NULL`` if the |namelen| is 0. The same thing
+ * can be said about the |value|.
+ *
+ * Please note that nghttp2 library does not perform any validity
+ * check against the |name| and the |value|. For example, the
+ * |namelen| could be 0, and/or the |value| contains ``0x0a`` or
+ * ``0x0d``.  The application must check them if it matters. The
+ * helper function `nghttp2_check_header_name()` and
+ * `nghttp2_check_header_value()` provide simple validation against
+ * HTTP2 header field construction rule.
+ *
+ * One more thing to note is that the |value| may contain ``NULL``
+ * (``0x00``) characters. It is used to concatenate header values
+ * which share the same header field name. The application should
+ * split these values if it wants to get individual value. This
+ * concatenation is used in order to keep the ordering of headers.
+ *
+ * If the application uses `nghttp2_session_mem_recv()`, it can return
+ * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`
+ * return without processing further input bytes.  The memory pointed
+ * by |frame|, |name| and |value| parameters are retained until
+ * `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is
+ * called. The application must retain the input bytes which was used
+ * to produce these parameters, because it may refer to the memory
+ * region included in the input bytes.
+ *
+ * Returning :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close
+ * the stream by issuing RST_STREAM with
+ * :enum:`NGHTTP2_INTERNAL_ERROR`. In this case,
+ * :type:`nghttp2_on_frame_recv_callback` will not be invoked.
+ *
+ * The implementation of this function must return 0 if it
+ * succeeds. It may return :enum:`NGHTTP2_ERR_PAUSE` or
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. For other critical
+ * failures, it must return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If
+ * the other nonzero value is returned, it is treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned,
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_header_callback)
+(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ const uint8_t *name, size_t namelen,
+ const uint8_t *value, size_t valuelen,
+ void *user_data);
+
+/**
+ * @struct
+ *
+ * Callback functions.
+ */
+typedef struct {
+  /**
+   * Callback function invoked when the |session| wants to send data
+   * to the remote peer.
+   */
+  nghttp2_send_callback send_callback;
+  /**
+   * Callback function invoked when the |session| wants to receive
+   * data from the remote peer.
+   */
+  nghttp2_recv_callback recv_callback;
+  /**
+   * Callback function invoked by `nghttp2_session_recv()` when a
+   * frame is received.
+   */
+  nghttp2_on_frame_recv_callback on_frame_recv_callback;
+  /**
+   * Callback function invoked by `nghttp2_session_recv()` when an
+   * invalid non-DATA frame is received.
+   */
+  nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback;
+  /**
+   * Callback function invoked when a chunk of data in DATA frame is
+   * received.
+   */
+  nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback;
+  /**
+   * Callback function invoked before a non-DATA frame is sent.
+   */
+  nghttp2_before_frame_send_callback before_frame_send_callback;
+  /**
+   * Callback function invoked after a frame is sent.
+   */
+  nghttp2_on_frame_send_callback on_frame_send_callback;
+  /**
+   * The callback function invoked when a non-DATA frame is not sent
+   * because of an error.
+   */
+  nghttp2_on_frame_not_send_callback on_frame_not_send_callback;
+  /**
+   * Callback function invoked when the stream is closed.
+   */
+  nghttp2_on_stream_close_callback on_stream_close_callback;
+  /**
+   * Callback function invoked when the received frame type is
+   * unknown.
+   */
+  nghttp2_on_unknown_frame_recv_callback on_unknown_frame_recv_callback;
+  /**
+   * Callback function invoked when the reception of header block in
+   * HEADERS or PUSH_PROMISE is started.
+   */
+  nghttp2_on_begin_headers_callback on_begin_headers_callback;
+  /**
+   * Callback function invoked when a header name/value pair is
+   * received.
+   */
+  nghttp2_on_header_callback on_header_callback;
+} nghttp2_session_callbacks;
+
+/**
+ * @function
+ *
+ * Initializes |*session_ptr| for client use. The all members of
+ * |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr|
+ * does not store |callbacks|. |user_data| is an arbitrary user
+ * supplied data, which will be passed to the callback functions.
+ *
+ * The :member:`nghttp2_session_callbacks.send_callback` must be
+ * specified.  If the application code uses `nghttp2_session_recv()`,
+ * the :member:`nghttp2_session_callbacks.recv_callback` must be
+ * specified. The other members of |callbacks| can be ``NULL``.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_session_client_new(nghttp2_session **session_ptr,
+                               const nghttp2_session_callbacks *callbacks,
+                               void *user_data);
+
+/**
+ * @function
+ *
+ * Initializes |*session_ptr| for server use. The all members of
+ * |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr|
+ * does not store |callbacks|. |user_data| is an arbitrary user
+ * supplied data, which will be passed to the callback functions.
+ *
+ * The :member:`nghttp2_session_callbacks.send_callback` must be
+ * specified.  If the application code uses `nghttp2_session_recv()`,
+ * the :member:`nghttp2_session_callbacks.recv_callback` must be
+ * specified. The other members of |callbacks| can be ``NULL``.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_session_server_new(nghttp2_session **session_ptr,
+                               const nghttp2_session_callbacks *callbacks,
+                               void *user_data);
+
+/**
+ * @enum
+ *
+ * Configuration options for :type:`nghttp2_session`.
+ */
+typedef enum {
+  /**
+   * This option prevents the library from sending WINDOW_UPDATE for a
+   * stream automatically. If this option is set to nonzero, the
+   * library won't send WINDOW_UPDATE for a stream and the application
+   * is responsible for sending WINDOW_UPDATE using
+   * `nghttp2_submit_window_update`. By default, this option is set to
+   * zero.
+   */
+  NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE = 1,
+  /**
+   * This option prevents the library from sending WINDOW_UPDATE for a
+   * connection automatically. If this option is set to nonzero, the
+   * library won't send WINDOW_UPDATE for a connection and the
+   * application is responsible for sending WINDOW_UPDATE with stream
+   * ID 0 using `nghttp2_submit_window_update`. By default, this
+   * option is set to zero.
+   */
+  NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE = 1 << 1,
+  /**
+   * This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of
+   * remote endpoint as if it is received in SETTINGS frame. Without
+   * specifying this option, before the local endpoint receives
+   * SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote
+   * endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may
+   * cause problem if local endpoint submits lots of requests
+   * initially and sending them at once to the remote peer may lead to
+   * the rejection of some requests. Specifying this option to the
+   * sensible value, say 100, may avoid this kind of issue. This value
+   * will be overwritten if the local endpoint receives
+   * SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
+   */
+  NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 2
+} nghttp2_opt;
+
+/**
+ * @struct
+ *
+ * Struct to store option values for nghttp2_session.
+ */
+typedef struct {
+  /**
+   * :enum:`NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS`
+   */
+  uint32_t peer_max_concurrent_streams;
+  /**
+   * :enum:`NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE`
+   */
+  uint8_t no_auto_stream_window_update;
+  /**
+   * :enum:`NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE`
+   */
+  uint8_t no_auto_connection_window_update;
+} nghttp2_opt_set;
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_client_new()`, but with additional options
+ * specified in the |opt_set|. The caller must set bitwise-OR of
+ * :enum:`nghttp2_opt` for given options.  For example, if it
+ * specifies :enum:`NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE` and
+ * :enum:`NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS` in the |opt_set|,
+ * the |opt_set_mask| should be
+ * ``NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE |
+ * NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS``.
+ *
+ * If the |opt_set_mask| is 0, the |opt_set| could be ``NULL`` safely
+ * and the call is equivalent to `nghttp2_session_client_new()`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_session_client_new2(nghttp2_session **session_ptr,
+                                const nghttp2_session_callbacks *callbacks,
+                                void *user_data,
+                                uint32_t opt_set_mask,
+                                const nghttp2_opt_set *opt_set);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_server_new()`, but with additional options
+ * specified in the |opt_set|. The caller must set bitwise-OR of
+ * :enum:`nghttp2_opt` for given options.  For example, if it
+ * specifies :enum:`NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE` and
+ * :enum:`NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS` in the |opt_set|,
+ * the |opt_set_mask| should be
+ * ``NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE |
+ * NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS``.
+ *
+ * If the |opt_set_mask| is 0, the |opt_set| could be ``NULL`` safely
+ * and the call is equivalent to `nghttp2_session_server_new()`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_session_server_new2(nghttp2_session **session_ptr,
+                                const nghttp2_session_callbacks *callbacks,
+                                void *user_data,
+                                uint32_t opt_set_mask,
+                                const nghttp2_opt_set *opt_set);
+
+/**
+ * @function
+ *
+ * Frees any resources allocated for |session|. If |session| is
+ * ``NULL``, this function does nothing.
+ */
+void nghttp2_session_del(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Sends pending frames to the remote peer.
+ *
+ * This function retrieves the highest prioritized frame from the
+ * outbound queue and sends it to the remote peer. It does this as
+ * many as possible until the user callback
+ * :member:`nghttp2_session_callbacks.send_callback` returns
+ * :enum:`NGHTTP2_ERR_WOULDBLOCK` or the outbound queue becomes empty.
+ * This function calls several callback functions which are passed
+ * when initializing the |session|. Here is the simple time chart
+ * which tells when each callback is invoked:
+ *
+ * 1. Get the next frame to send from outbound queue.
+ * 2. Prepare transmission of the frame.
+ * 3. If the control frame cannot be sent because some preconditions
+ *    are not met (e.g., request HEADERS cannot be sent after
+ *    GOAWAY),
+ *    :member:`nghttp2_session_callbacks.on_frame_not_send_callback` is
+ *    invoked. Abort the following steps.
+ * 4. If the frame is request HEADERS, the stream is opened
+ *    here.
+ * 5. :member:`nghttp2_session_callbacks.before_frame_send_callback` is
+ *    invoked.
+ * 6. :member:`nghttp2_session_callbacks.send_callback` is invoked one
+ *    or more times to send the frame.
+ * 7. :member:`nghttp2_session_callbacks.on_frame_send_callback` is
+ *    invoked.
+ * 8. If the transmission of the frame triggers closure of the stream,
+ *    the stream is closed and
+ *    :member:`nghttp2_session_callbacks.on_stream_close_callback` is
+ *    invoked.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
+ *     The callback function failed.
+ */
+int nghttp2_session_send(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Receives frames from the remote peer.
+ *
+ * This function receives as many frames as possible until the user
+ * callback :member:`nghttp2_session_callbacks.recv_callback` returns
+ * :enum:`NGHTTP2_ERR_WOULDBLOCK`. This function calls several
+ * callback functions which are passed when initializing the
+ * |session|. Here is the simple time chart which tells when each
+ * callback is invoked:
+ *
+ * 1. :member:`nghttp2_session_callbacks.recv_callback` is invoked one
+ *    or more times to receive frame header.
+ * 2. If the frame is DATA frame:
+ *
+ *    1. :member:`nghttp2_session_callbacks.recv_callback` is invoked
+ *       to receive DATA payload. For each chunk of data,
+ *       :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback`
+ *       is invoked.
+ *    2. If one DATA frame is completely received,
+ *       :member:`nghttp2_session_callbacks.on_frame_recv_callback` is
+ *       invoked. If the reception of the frame triggers the
+ *       closure of the stream,
+ *       :member:`nghttp2_session_callbacks.on_stream_close_callback`
+ *       is invoked.
+ *
+ * 3. If the frame is the control frame:
+ *
+ *    1. :member:`nghttp2_session_callbacks.recv_callback` is invoked
+ *       one or more times to receive whole frame.
+ *
+ *    2. If the received frame is valid, then following actions are
+ *       taken. If the frame is either HEADERS or PUSH_PROMISE,
+ *       :member:`nghttp2_session_callbacks.on_begin_headers_callback`
+ *       is invoked. Then
+ *       :member:`nghttp2_session_callbacks.on_header_callback` is
+ *       invoked for each header name/value pair. After all name/value
+ *       pairs are emitted successfully,
+ *       :member:`nghttp2_session_callbacks.on_frame_recv_callback` is
+ *       invoked.  For other frames,
+ *       :member:`nghttp2_session_callbacks.on_frame_recv_callback` is
+ *       invoked.
+ *       If the reception of the frame triggers the closure of the
+ *       stream,
+ *       :member:`nghttp2_session_callbacks.on_stream_close_callback`
+ *       is invoked.
+ *    3. If the received frame is unpacked but is interpreted as
+ *       invalid,
+ *       :member:`nghttp2_session_callbacks.on_invalid_frame_recv_callback`
+ *       is invoked.
+ *    4. If the received frame type is unknown,
+ *       :member:`nghttp2_session_callbacks.on_unknown_frame_recv_callback`
+ *       is invoked.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_EOF`
+ *     The remote peer did shutdown on the connection.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
+ *     The callback function failed.
+ */
+int nghttp2_session_recv(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Processes data |in| as an input from the remote endpoint. The
+ * |inlen| indicates the number of bytes in the |in|.
+ *
+ * This function behaves like `nghttp2_session_recv()` except that it
+ * does not use :member:`nghttp2_session_callbacks.recv_callback` to
+ * receive data; the |in| is the only data for the invocation of this
+ * function. If all bytes are processed, this function returns. The
+ * other callbacks are called in the same way as they are in
+ * `nghttp2_session_recv()`.
+ *
+ * In the current implementation, this function always tries to
+ * processes all input data unless either an error occurs or
+ * :enum:`NGHTTP2_ERR_PAUSE` is returned from
+ * :member:`nghttp2_session_callbacks.on_header_callback` or
+ * :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback`.
+ * If :enum:`NGHTTP2_ERR_PAUSE` is used, the return value includes the
+ * number of bytes which was used to produce the data or frame for the
+ * callback.
+ *
+ * This function returns the number of processed bytes, or one of the
+ * following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
+ *     The callback function failed.
+ */
+ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
+                                 const uint8_t *in, size_t inlen);
+
+/**
+ * @function
+ *
+ * Puts back previously deferred DATA frame in the stream |stream_id|
+ * to the outbound queue.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ *     The stream does not exist or no deferred data exist.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns nonzero value if |session| wants to receive data from the
+ * remote peer.
+ *
+ * If both `nghttp2_session_want_read()` and
+ * `nghttp2_session_want_write()` return 0, the application should
+ * drop the connection.
+ */
+int nghttp2_session_want_read(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns nonzero value if |session| wants to send data to the remote
+ * peer.
+ *
+ * If both `nghttp2_session_want_read()` and
+ * `nghttp2_session_want_write()` return 0, the application should
+ * drop the connection.
+ */
+int nghttp2_session_want_write(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns stream_user_data for the stream |stream_id|. The
+ * stream_user_data is provided by `nghttp2_submit_request()`,
+ * `nghttp2_submit_headers()` or
+ * `nghttp2_session_set_stream_user_data()`. Unless it is set using
+ * `nghttp2_session_set_stream_user_data()`, if the stream is
+ * initiated by the remote endpoint, stream_user_data is always
+ * ``NULL``. If the stream does not exist, this function returns
+ * ``NULL``.
+ */
+void* nghttp2_session_get_stream_user_data(nghttp2_session *session,
+                                           int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Sets the |stream_user_data| to the stream denoted by the
+ * |stream_id|. If a stream user data is already set to the stream, it
+ * is replaced with the |stream_user_data|. It is valid to specify
+ * ``NULL`` in the |stream_user_data|, which nullifies the associated
+ * data pointer.
+ *
+ * It is valid to set the |stream_user_data| to the stream reserved by
+ * PUSH_PROMISE frame.
+ *
+ * This function returns 0 if it succeeds, or one of following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ *     The stream does not exist
+ */
+int nghttp2_session_set_stream_user_data(nghttp2_session *session,
+                                         int32_t stream_id,
+                                         void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Returns the number of frames in the outbound queue. This does not
+ * include the deferred DATA frames.
+ */
+size_t nghttp2_session_get_outbound_queue_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the number of DATA payload in bytes received without
+ * WINDOW_UPDATE transmission for the stream |stream_id|. The local
+ * (receive) window size can be adjusted by
+ * `nghttp2_submit_window_update()`. This function takes into account
+ * that and returns effective data length. In particular, if the
+ * local window size is reduced by submitting negative
+ * window_size_increment with `nghttp2_submit_window_update()`, this
+ * function returns the number of bytes less than actually received.
+ *
+ * If flow control is disabled for that stream, this function returns
+ * 0.
+ *
+ * This function returns -1 if it fails.
+ */
+int32_t nghttp2_session_get_stream_effective_recv_data_length
+(nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the local (receive) window size for the stream
+ * |stream_id|. The local window size can be adjusted by
+ * `nghttp2_submit_window_update()`. This function takes into account
+ * that and returns effective window size.
+ *
+ * This function returns -1 if it fails.
+ */
+int32_t nghttp2_session_get_stream_effective_local_window_size
+(nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the number of DATA payload in bytes received without
+ * WINDOW_UPDATE transmission for a connection. The local (receive)
+ * window size can be adjusted by
+ * `nghttp2_submit_window_update()`. This function takes into account
+ * that and returns effective data length. In particular, if the local
+ * window size is reduced by submitting negative window_size_increment
+ * with `nghttp2_submit_window_update()`, this function returns the
+ * number of bytes less than actually received.
+ *
+ * If flow control is disabled for a connection, this function returns
+ * 0.
+ *
+ * This function returns -1 if it fails.
+ */
+int32_t nghttp2_session_get_effective_recv_data_length
+(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the local (receive) window size for a connection. The local
+ * window size can be adjusted by
+ * `nghttp2_submit_window_update()`. This function takes into account
+ * that and returns effective window size.
+ *
+ * This function returns -1 if it fails.
+ */
+int32_t nghttp2_session_get_effective_local_window_size
+(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Signals the session so that the connection should be terminated.
+ *
+ * GOAWAY frame with the given |error_code| will be submitted if it
+ * has not been transmitted. After the transmission, both
+ * `nghttp2_session_want_read()` and `nghttp2_session_want_write()`
+ * return 0. If GOAWAY frame has already transmitted at the time when
+ * this function is invoked, `nghttp2_session_want_read()` and
+ * `nghttp2_session_want_write()` returns 0 immediately after this
+ * function succeeds.
+ *
+ * This function should be called when the connection should be
+ * terminated after sending GOAWAY. If the remaining streams should be
+ * processed after GOAWAY, use `nghttp2_submit_goaway()` instead.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_session_terminate_session(nghttp2_session *session,
+                                      nghttp2_error_code error_code);
+
+/**
+ * @function
+ *
+ * Performs post-process of HTTP Upgrade request. This function can be
+ * called from both client and server, but the behavior is very
+ * different in each other.
+ *
+ * If called from client side, the |settings_payload| must be the
+ * value sent in ``HTTP2-Settings`` header field and must be decoded
+ * by base64url decoder. The |settings_payloadlen| is the length of
+ * |settings_payload|. The |settings_payload| is unpacked and its
+ * setting values will be submitted using
+ * `nghttp2_submit_settings()`. This means that the client application
+ * code does not need to submit SETTINGS by itself. The stream with
+ * stream ID=1 is opened and the |stream_user_data| is used for its
+ * stream_user_data. The opened stream becomes half-closed (local)
+ * state.
+ *
+ * If called from server side, the |settings_payload| must be the
+ * value received in ``HTTP2-Settings`` header field and must be
+ * decoded by base64url decoder. The |settings_payloadlen| is the
+ * length of |settings_payload|. It is treated as if the SETTINGS
+ * frame with that payload is received. Thus, callback functions for
+ * the reception of SETTINGS frame will be invoked. The stream with
+ * stream ID=1 is opened. The |stream_user_data| is ignored. The
+ * opened stream becomes half-closed (remote).
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ *     The |settings_payload| is badly formed.
+ * :enum:`NGHTTP2_ERR_PROTO`
+ *     The stream ID 1 is already used or closed; or is not available;
+ *     or the |settings_payload| does not include both
+ *     :enum:`NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS` and
+ *     :enum:`NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE`.
+ */
+int nghttp2_session_upgrade(nghttp2_session *session,
+                            const uint8_t *settings_payload,
+                            size_t settings_payloadlen,
+                            void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Serializes the SETTINGS values |iv| in the |buf|. The size of the
+ * |buf| is specified by |buflen|. The number of entries in the |iv|
+ * array is given by |niv|. The required space in |buf| for the |niv|
+ * entries is ``8*niv`` bytes and if the given buffer is too small, an
+ * error is returned. This function is used mainly for creating a
+ * SETTINGS payload to be sent with the ``HTTP2-Settings`` header
+ * field in an HTTP Upgrade request. The data written in |buf| is NOT
+ * base64url encoded and the application is responsible for encoding.
+ *
+ * This function returns the number of bytes written in |buf|, or one
+ * of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ *     The |iv| contains duplicate settings ID or invalid value.
+ *
+ * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
+ *     The provided |buflen| size is too small to hold the output.
+ */
+ssize_t nghttp2_pack_settings_payload(uint8_t *buf,
+                                      size_t buflen,
+                                      const nghttp2_settings_entry *iv,
+                                      size_t niv);
+
+/**
+ * @function
+ *
+ * Returns string describing the |lib_error_code|. The
+ * |lib_error_code| must be one of the :enum:`nghttp2_error`.
+ */
+const char* nghttp2_strerror(int lib_error_code);
+
+/**
+ * @function
+ *
+ * Submits HEADERS frame and optionally one or more DATA frames.
+ *
+ * The |pri| is priority of this request. 0 is the highest priority
+ * value and :macro:`NGHTTP2_PRI_LOWEST` is the lowest value.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The value is opaque sequence of bytes and
+ * therefore can contain NULL byte (0x0). If the application requires
+ * that the ordering of values for a single header field name
+ * appearing in different header fields, it has to concatenate them
+ * using NULL byte (0x0) before passing them to this function.
+ *
+ * HTTP/2.0 specification has requirement about header fields in the
+ * request HEADERS. See the specification for more details.
+ *
+ * This function creates copies of all name/value pairs in |nva|.  It
+ * also lower-cases all names in |nva|.
+ *
+ * If |data_prd| is not ``NULL``, it provides data which will be sent
+ * in subsequent DATA frames. In this case, a method that allows
+ * request message bodies
+ * (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9) must
+ * be specified with ``:method`` key in |nva| (e.g. ``POST``). This
+ * function does not take ownership of the |data_prd|. The function
+ * copies the members of the |data_prd|. If |data_prd| is ``NULL``,
+ * HEADERS have END_STREAM set. The |stream_user_data| is data
+ * associated to the stream opened by this request and can be an
+ * arbitrary pointer, which can be retrieved later by
+ * `nghttp2_session_get_stream_user_data()`.
+ *
+ * Since the library reorders the frames and tries to send the highest
+ * prioritized one first and the HTTP/2.0 specification requires the
+ * stream ID must be strictly increasing, the stream ID of this
+ * request cannot be known until it is about to sent.  To know the
+ * stream ID of the request, the application can use
+ * :member:`nghttp2_session_callbacks.before_frame_send_callback`. This
+ * callback is called just before the frame is sent. For HEADERS
+ * frame, the argument frame has the stream ID assigned. Also since
+ * the stream is already opened,
+ * `nghttp2_session_get_stream_user_data()` can be used to get
+ * |stream_user_data| to identify which HEADERS we are processing.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ *     The |pri| is invalid
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_submit_request(nghttp2_session *session, int32_t pri,
+                           const nghttp2_nv *nva, size_t nvlen,
+                           const nghttp2_data_provider *data_prd,
+                           void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Submits response HEADERS frame and optionally one or more DATA
+ * frames against the stream |stream_id|.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The value is opaque sequence of bytes and
+ * therefore can contain NULL byte (0x0). If the application requires
+ * that the ordering of values for a single header field name
+ * appearing in different header fields, it has to concatenate them
+ * using NULL byte (0x0) before passing them to this function.
+ *
+ * HTTP/2.0 specification has requirement about header fields in the
+ * response HEADERS. See the specification for more details.
+ *
+ * This function creates copies of all name/value pairs in |nva|.  It
+ * also lower-cases all names in |nva|.
+ *
+ * If |data_prd| is not ``NULL``, it provides data which will be sent
+ * in subsequent DATA frames.  This function does not take ownership
+ * of the |data_prd|. The function copies the members of the
+ * |data_prd|.  If |data_prd| is ``NULL``, HEADERS will have
+ * END_STREAM flag set.
+ *
+ * This method can be used as normal HTTP response and push
+ * response. When pushing a resource using this function, the
+ * |session| must be configured using `nghttp2_session_server_new()`
+ * or its variants and the target stream denoted by the |stream_id|
+ * must be reserved using `nghttp2_submit_push_promise()`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_submit_response(nghttp2_session *session,
+                            int32_t stream_id,
+                            const nghttp2_nv *nva, size_t nvlen,
+                            const nghttp2_data_provider *data_prd);
+
+/**
+ * @function
+ *
+ * Submits HEADERS frame. The |flags| is bitwise OR of the
+ * following values:
+ *
+ * * :enum:`NGHTTP2_FLAG_END_STREAM`
+ * * :enum:`NGHTTP2_FLAG_END_HEADERS`
+ * * :enum:`NGHTTP2_FLAG_PRIORITY`
+ *
+ * If |flags| includes :enum:`NGHTTP2_FLAG_END_STREAM`, this frame has
+ * END_STREAM flag set. The library does not support header
+ * continuation and the HEADERS frame always has
+ * :enum:`NGHTTP2_FLAG_END_HEADERS` flag set regardless of the |flags|
+ * value.
+ *
+ * If the |stream_id| is -1, this frame is assumed as request (i.e.,
+ * request HEADERS frame which opens new stream). In this case, the
+ * actual stream ID is assigned just before the frame is sent. For
+ * response, specify stream ID in |stream_id|.
+ *
+ * The |pri| is priority of this request.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The value is opaque sequence of bytes and
+ * therefore can contain NULL byte (0x0). If the application requires
+ * that the ordering of values for a single header field name
+ * appearing in different header fields, it has to concatenate them
+ * using NULL byte (0x0) before passing them to this function.
+ *
+ * This function creates copies of all name/value pairs in |nva|.  It
+ * also lower-cases all names in |nva|.
+ *
+ * The |stream_user_data| is a pointer to an arbitrary data which is
+ * associated to the stream this frame will open. Therefore it is only
+ * used if this frame opens streams, in other words, it changes stream
+ * state from idle or reserved to open.
+ *
+ * This function is low-level in a sense that the application code can
+ * specify flags directly. For usual HTTP request,
+ * `nghttp2_submit_request()` is useful.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ *     The |pri| is invalid
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
+                           int32_t stream_id, int32_t pri,
+                           const nghttp2_nv *nva, size_t nvlen,
+                           void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Submits one or more DATA frames to the stream |stream_id|.  The
+ * data to be sent are provided by |data_prd|. If |flags| contains
+ * :enum:`NGHTTP2_FLAG_END_STREAM`, the last DATA frame has END_STREAM
+ * flag set.
+ *
+ * This function does not take ownership of the |data_prd|. The
+ * function copies the members of the |data_prd|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
+                        int32_t stream_id,
+                        const nghttp2_data_provider *data_prd);
+
+/**
+ * @function
+ *
+ * Submits PRIORITY frame to change the priority of stream |stream_id|
+ * to the priority value |pri|.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ *     The |pri| is negative.
+ */
+int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
+                            int32_t stream_id, int32_t pri);
+
+/**
+ * @function
+ *
+ * Submits RST_STREAM frame to cancel/reject the stream |stream_id|
+ * with the error code |error_code|.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags,
+                              int32_t stream_id,
+                              nghttp2_error_code error_code);
+
+/**
+ * @function
+ *
+ * Stores local settings and submits SETTINGS frame. The |iv| is the
+ * pointer to the array of :type:`nghttp2_settings_entry`. The |niv|
+ * indicates the number of :type:`nghttp2_settings_entry`.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * This function does not take ownership of the |iv|. This function
+ * copies all the elements in the |iv|.
+ *
+ * While updating individual stream's local window size, if the window
+ * size becomes strictly larger than NGHTTP2_MAX_WINDOW_SIZE,
+ * RST_STREAM is issued against such a stream.
+ *
+ * SETTINGS with :enum:`NGHTTP2_FLAG_ACK` is automatically submitted
+ * by the library and application could not send it at its will.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ *     The |iv| contains invalid value (e.g., attempting to re-enable
+ *     flow control).
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
+                            const nghttp2_settings_entry *iv, size_t niv);
+
+
+/**
+ * @function
+ *
+ * Submits PUSH_PROMISE frame. The |flags| is currently ignored and
+ * the resulting PUSH_PROMISE frame always has
+ * :enum:`NGHTTP2_FLAG_END_PUSH_PROMISE` flag set due to the lack of
+ * header continuation support in the library.
+ *
+ * The |stream_id| must be client initiated stream ID.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The value is opaque sequence of bytes and
+ * therefore can contain NULL byte (0x0). If the application requires
+ * that the ordering of values for a single header field name
+ * appearing in different header fields, it has to concatenate them
+ * using NULL byte (0x0) before passing them to this function.
+ *
+ * This function creates copies of all name/value pairs in |nva|.  It
+ * also lower-cases all names in |nva|.
+ *
+ * Since the library reorders the frames and tries to send the highest
+ * prioritized one first and the HTTP/2.0 specification requires the
+ * stream ID must be strictly increasing, the promised stream ID
+ * cannot be known until it is about to sent.  To know the promised
+ * stream ID, the application can use
+ * :member:`nghttp2_session_callbacks.before_frame_send_callback`. This
+ * callback is called just before the frame is sent. For PUSH_PROMISE
+ * frame, the argument frame has the promised stream ID assigned.
+ *
+ * The client side can use this function to send PUSH_PROMISE to the
+ * server. But in normal HTTP usage, the server may treat it error.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
+                                int32_t stream_id,
+                                const nghttp2_nv *nva, size_t nvlen);
+
+/**
+ * @function
+ *
+ * Submits PING frame. You don't have to send PING back when you
+ * received PING frame. The library automatically submits PING frame
+ * in this case.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * If the |opaque_data| is non ``NULL``, then it should point to the 8
+ * bytes array of memory to specify opaque data to send with PING
+ * frame. If the |opaque_data| is ``NULL``, zero-cleared 8 bytes will
+ * be sent as opaque data.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
+                        uint8_t *opaque_data);
+
+/**
+ * @function
+ *
+ * Submits GOAWAY frame with the error code |error_code|.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * If the |opaque_data| is not ``NULL`` and |opaque_data_len| is not
+ * zero, those data will be sent as additional debug data.  The
+ * library makes a copy of the memory region pointed by |opaque_data|
+ * with the length |opaque_data_len|, so the caller does not need to
+ * keep this memory after the return of this function. If the
+ * |opaque_data_len| is 0, the |opaque_data| could be ``NULL``.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
+                          nghttp2_error_code error_code,
+                          uint8_t *opaque_data, size_t opaque_data_len);
+
+/**
+ * @function
+ *
+ * Submits WINDOW_UPDATE frame.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * If the |window_size_increment| is positive, the WINDOW_UPDATE with
+ * that value as window_size_increment is queued. If the
+ * |window_size_increment| is larger than the received bytes from the
+ * remote endpoint, the local window size is increased by that
+ * difference.
+ *
+ * If the |window_size_increment| is negative, the local window size
+ * is decreased by -|window_size_increment|.  If
+ * :enum:`NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE` (or
+ * :enum:`NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE` if |stream_id|
+ * is 0) is not set and the library decided that the WINDOW_UPDATE
+ * should be submitted, then WINDOW_UPDATE is queued with the current
+ * received bytes count.
+ *
+ * If the |window_size_increment| is 0, the function does nothing and
+ * returns 0.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_FLOW_CONTROL`
+ *     The local window size overflow or gets negative.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
+                                 int32_t stream_id,
+                                 int32_t window_size_increment);
+
+/**
+ * @function
+ *
+ * Compares lhs->name with lhs->namelen bytes and rhs->name with
+ * rhs->namelen bytes. Returns negative integer if lhs->name is found
+ * to be less than rhs->name; or returns positive integer if lhs->name
+ * is found to be greater than rhs->name; or returns 0 otherwise.
+ */
+int nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs);
+
+/**
+ * @function
+ *
+ * A helper function for dealing with NPN in client side or ALPN in
+ * server side. The |in| contains peer's protocol list in preferable
+ * order.  The format of |in| is length-prefixed and not
+ * null-terminated.  For example, ``HTTP-draft-04/2.0`` and
+ * ``http/1.1`` stored in |in| like this::
+ *
+ *     in[0] = 17
+ *     in[1..17] = "HTTP-draft-04/2.0"
+ *     in[18] = 8
+ *     in[19..26] = "http/1.1"
+ *     inlen = 27
+ *
+ * The selection algorithm is as follows:
+ *
+ * 1. If peer's list contains HTTP/2.0 protocol the library supports,
+ *    it is selected and returns 1. The following step is not taken.
+ *
+ * 2. If peer's list contains ``http/1.1``, this function selects
+ *    ``http/1.1`` and returns 0. The following step is not taken.
+ *
+ * 3. This function selects nothing and returns -1. (So called
+ *    non-overlap case). In this case, |out| and |outlen| are left
+ *    untouched.
+ *
+ * Selecting ``HTTP-draft-04/2.0`` means that ``HTTP-draft-04/2.0`` is
+ * written into |*out| and its length (which is 17) is
+ * assigned to |*outlen|.
+ *
+ * For ALPN, refer to
+ * http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04
+ *
+ * See http://technotes.googlecode.com/git/nextprotoneg.html for more
+ * details about NPN.
+ *
+ * For NPN, to use this method you should do something like::
+ *
+ *     static int select_next_proto_cb(SSL* ssl,
+ *                                     unsigned char **out,
+ *                                     unsigned char *outlen,
+ *                                     const unsigned char *in,
+ *                                     unsigned int inlen,
+ *                                     void *arg)
+ *     {
+ *         int rv;
+ *         rv = nghttp2_select_next_protocol(out, outlen, in, inlen);
+ *         if(rv == 1) {
+ *             ((MyType*)arg)->http2_selected = 1;
+ *         }
+ *         return SSL_TLSEXT_ERR_OK;
+ *     }
+ *     ...
+ *     SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, my_obj);
+ *
+ */
+int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen,
+                                 const unsigned char *in, unsigned int inlen);
+
+struct nghttp2_gzip;
+
+/**
+ * @struct
+ *
+ * The gzip stream to inflate data. The details of this structure are
+ * intentionally hidden from the public API.
+ */
+typedef struct nghttp2_gzip nghttp2_gzip;
+
+/**
+ * @function
+ *
+ * A helper function to set up a per request gzip stream to inflate data.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_GZIP`
+ *     The initialization of gzip stream failed.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ */
+int nghttp2_gzip_inflate_new(nghttp2_gzip **inflater_ptr);
+
+/**
+ * @function
+ *
+ * Frees the inflate stream.  The |inflater| may be ``NULL``.
+ */
+void nghttp2_gzip_inflate_del(nghttp2_gzip *inflater);
+
+/**
+ * @function
+ *
+ * Inflates data in |in| with the length |*inlen_ptr| and stores the
+ * inflated data to |out| which has allocated size at least
+ * |*outlen_ptr|. On return, |*outlen_ptr| is updated to represent
+ * the number of data written in |out|.  Similarly, |*inlen_ptr| is
+ * updated to represent the number of input bytes processed.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_GZIP`
+ *     The inflation of gzip stream failed.
+ *
+ * The example follows::
+ *
+ *     void on_data_chunk_recv_callback(nghttp2_session *session,
+ *                                      uint8_t flags,
+ *                                      int32_t stream_id,
+ *                                      const uint8_t *data, size_t len,
+ *                                      void *user_data)
+ *     {
+ *         ...
+ *         req = nghttp2_session_get_stream_user_data(session, stream_id);
+ *         nghttp2_gzip *inflater = req->inflater;
+ *         while(len > 0) {
+ *             uint8_t out[MAX_OUTLEN];
+ *             size_t outlen = MAX_OUTLEN;
+ *             size_t tlen = len;
+ *             int rv;
+ *             rv = nghttp2_gzip_inflate(inflater, out, &outlen, data, &tlen);
+ *             if(rv != 0) {
+ *                 nghttp2_submit_rst_stream(session, stream_id,
+ *                                           NGHTTP2_INTERNAL_ERROR);
+ *                 break;
+ *             }
+ *             ... Do stuff ...
+ *             data += tlen;
+ *             len -= tlen;
+ *         }
+ *         ....
+ *     }
+ */
+int nghttp2_gzip_inflate(nghttp2_gzip *inflater,
+                         uint8_t *out, size_t *outlen_ptr,
+                         const uint8_t *in, size_t *inlen_ptr);
+
+/**
+ * @function
+ *
+ * Returns a pointer to a nghttp2_info struct with version information about
+ * the run-time library in use.  The |least_version| argument can be set to a
+ * 24 bit numerical value for the least accepted version number and if the
+ * condition is not met, this function will return a NULL. Pass in 0 to skip
+ * the version checking.
+ */
+nghttp2_info *nghttp2_version(int least_version);
+
+/**
+ * @function
+ *
+ * Returns nonzero if the :type:`nghttp2_error` library error code
+ * |lib_error| is fatal.
+ */
+int nghttp2_is_fatal(int lib_error);
+
+/**
+ * @function
+ *
+ * Returns nonzero if HTTP header field name |name| of length |len| is
+ * valid according to
+ * http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-25#section-3.2
+ *
+ * Because this is a header field name in HTTP2, the upper cased alphabet
+ * is treated as error.
+ */
+int nghttp2_check_header_name(const uint8_t *name, size_t len);
+
+/**
+ * @function
+ *
+ * Returns nonzero if HTTP header field value |value| of length |len|
+ * is valid according to
+ * http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-25#section-3.2
+ *
+ * Because this is HTTP2 header field value, it can contain NULL
+ * character (0x00).
+ */
+int nghttp2_check_header_value(const uint8_t *value, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NGHTTP2_H */
+
+
+
+ + +
+ +
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/released-versions/v0.3.0/nghttp2ver.h.html b/released-versions/v0.3.0/nghttp2ver.h.html new file mode 100644 index 00000000..6b246582 --- /dev/null +++ b/released-versions/v0.3.0/nghttp2ver.h.html @@ -0,0 +1,229 @@ + + + + + + + + + + + nghttp2ver.h — nghttp2 0.3.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+ +
+

nghttp2ver.h¶

+
/*
+ * nghttp2 - HTTP/2.0 C Library
+ *
+ * Copyright (c) 2012, 2013 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.
+ */
+#ifndef NGHTTP2VER_H
+#define NGHTTP2VER_H
+
+/**
+ * @macro
+ * Version number of the nghttp2 library release
+ */
+#define NGHTTP2_VERSION "0.3.0"
+
+/**
+ * @macro
+ * Numerical representation of the version number of the nghttp2 library
+ * release. This is a 24 bit number with 8 bits for major number, 8 bits
+ * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
+ */
+#define NGHTTP2_VERSION_NUM 0x000300
+
+#endif /* NGHTTP2VER_H */
+
+
+
+ + +
+ +
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/released-versions/v0.3.0/objects.inv b/released-versions/v0.3.0/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..9b18db6d496bed4c4376fe0834560e03ecc25042 GIT binary patch literal 2128 zcmV-W2(R}eAX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkzXJ~YE za54%bAXa5^b7^mGIv_AEGcGU+BOp|0Wgv28ZDDC{WMy(7Z)PBLXlZjGW@&6?AZc?T zV{dJ6a%FRKWn>_Ab7^j8AbM5YnjY*WFA;o)@p>*op(hS;&L+_Oq0L7@9O_na#oc$yU{`?;u_^h+K;vwZRSuSNOx z`7r#$*f)p#kHwm&ZO#_9_|vByD=sXOe;rozkJc=%lKuR_{%^x$LI1!e-my=`Zr?QJ z9pz<1Yt|SAr*YeGn((4vNt5w{zQQN?D{ad(ZrCFEa$tvNRxSQo#AQ~oZU53g7oR`5 z_YYyXxueAQsqKC<9owQoXof^Aij#_8SR=n*w)LKt6+dJ(Gm2x*ifdnztBRv>jPsUZ zo~>D33v-e<&!6Mur8eM~Z51CFEx0hgNXP$St$ZM+MSQyS)|)Ff$`t_#L)*O%JS>(KQIo0&F)#8vTC}?=B;E`O>Ua3*wvI3P4)Ki^Kyf>8xr3&9bud2BP`nZHg&v5 z5`;JldUsbWIciyPA#jk3F-`Vu@pAS$WhQjHF!m`X%1g&4ZU_-}U9t>q&y~S*h>Ng! z$K%)dO>JXULk2b#iw_2?Dh@&BDJrW=h_Cwf@2k826uz?Ghav@3Nxp2`qC*HI6s&x6 zP0&75#Ag;u+L^CR?>R2{#9UL`LTu<_0%ipuPnLd=(zl_}5SAq8HPd`s4q#0S_OlTn z+VF(m5TGHmzdGLX?_1oW&O^ZK0^Eg#*UvNHxXPY9$z|zx?V_4NANuhiN7m& zSa7G%_Z*Z@d%lY7{URkqcyWlk`<0c@wYNEBogRT%0ZL)EFQY5MjM{(SJ;tI&Y{z!( z&<27&;iI_Po7&@gYqG|6P%{b$8lO%y7GpmIgBu-P5sQ9P!)Y@x*?|?olFo2Fv?}s8 zA>9z*5&{|_Qp?Eqg^1|OD8RsR&)4zVsAknsbYAv)hpUEJx5G&xkq#DF!4Fi&nttIH zk%z{sb4sO{9?U2vSp%gK6$Qxl6?!*RyX{0i!4qH|b*FAZ9c7jL4)h69Xm)xSynW2T z2L^mf59=ka+?=u9_iNr(i73T5)gTZfRSE4i@uEIUIM*nzBjuS>Wn}f*gc$5Vt(%b(-XxH3oXKd9 z8U?qo-N+1aVyGkN#I-sVBuZ^<2iUGDWrgYAM{6h!ECmu%kIwDN{xR!|0Oy@gi}rwV zM6X^kl?nuCcjM6QLy4daFLLB}NxkUd(ddt*8B(A86J4K8o+Sp}kAhFCEg4^|6c*E@ zA>ImWqk6;gaoJPcXst0fz;ZvN1OgRrpfvT_DroAvX0L;@@L-pCIFNnUQKV-4kP^UPb|QvbHBWnJ6CIb@{PNU1wI#C;Hk z(I+qR1+7}^NGBW>#gD(l(Tq=mF7dJay{oIPL%_<7=b{AAv`24K4f!`ChlsHBopK-# z%8v}g^gJHFf~>n?cc=LSLY)fX13Jl!fWZzkgMoHL8w)pu>#dWus8j7C*9Qw*kV6{u z>cSh?b}LRlkBsIVGM`R3AI=pW?gNYRd^>!)^^8GtaC4fnqb6$CPcRhg2YP}=lD2p$ z`0M|90(gEJikxWa4PHTtQmE zq`FfHjiZrCP=T}Plv|!byBBj4J(8f#SwZ6U)xM7Q%~GBDP?72#OyL@FxBsO^_Rgg= zE{&&?TMfZHPDA>xtWz*;xvS!o>D9;#ovz~@Dyi>1^U-{wrUSWcJpmy{Yfjq@qScCi zjaJAL897E*WmC@yCPkn_BQM>uL0(`nitLDklos@U~hqH#uRi1~sRacfw0$O>^Pa~h~>l$~1Py_*Rr zDg6j;*j_Ru>Gd4FM3T>sanMA0a+IjPbkVh7^9?tYe1EB{WI(bG@lSDQGij?z5SpIt zp~`U9D{)k}+o)v+!i5%gpc(I&9%q#&TKXdHx7C~8(0nXONZ%7ZE91AEs|d6FplS=t8Q8ByKddTksHt^bvXK7(G=POrE1R!nwmm zMdUT~k(WUatQ+KYl(WW3v0uA3uDXp_j^u5)NQ-J3>H?e0L@_i48rY$Xp(5262>%0i Go1l_@mKN*) literal 0 HcmV?d00001 diff --git a/released-versions/v0.3.0/package_README.html b/released-versions/v0.3.0/package_README.html new file mode 100644 index 00000000..00806280 --- /dev/null +++ b/released-versions/v0.3.0/package_README.html @@ -0,0 +1,1083 @@ + + + + + + + + + + + nghttp2 - HTTP/2.0 C Library — nghttp2 0.3.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+ +
+

nghttp2 - HTTP/2.0 C Library¶

+

This is an experimental implementation of Hypertext Transfer Protocol +version 2.0.

+
+

Development Status¶

+

We started to implement HTTP-draft-09/2.0 +(http://tools.ietf.org/html/draft-ietf-httpbis-http2-09) and the +header compression +(http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05).

+

The nghttp2 code base was forked from spdylay project.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeaturesHTTP-draft-09/2.0
:authorityDone
HPACK-draft-05Done
SETTINGS_HEADER_TABLE_SIZEDone
SETTINGS_ENABLE_PUSHDone
FRAME_SIZE_ERRORDone
SETTINGS with ACKDone
Header ContinuationDone
ALPNDone
+
+
+

Public Test Server¶

+

The following endpoints are available to try out nghttp2 +implementation. These endpoints supports HTTP-draft-09/2.0 and +the earlier draft versions are not supporeted.

+
    +
  • https://106.186.112.116 (TLS + NPN / ALPN)

    +

    ALPN and NPN offer HTTP-draft-09/2.0, spdy/3.1, spdy/3, +spdy/2 and http/1.1.

    +

    Note: certificate is self-signed and a browser will show alert

    +
  • +
  • http://106.186.112.116 (Upgrade + Direct)

    +
  • +
+
+
+

Requirements¶

+

The following packages are needed to build the library:

+
    +
  • pkg-config >= 0.20
  • +
  • zlib >= 1.2.3
  • +
+

To build and run the unit test programs, the following packages are +required:

+
    +
  • cunit >= 2.1
  • +
+

To build the documentation, you need to install:

+ +

To build and run the application programs (nghttp, nghttpd and +nghttpx) in src directory, the following packages are +required:

+
    +
  • OpenSSL >= 1.0.1
  • +
  • libevent-openssl >= 2.0.8
  • +
+

ALPN support requires unreleased version OpenSSL >= 1.0.2.

+

To enable SPDY protocol in the application program nghttpx, the +following packages are required:

+
    +
  • spdylay >= 1.2.3
  • +
+

To enable -a option (getting linked assets from the downloaded +resource) in nghttp, the following packages are needed:

+
    +
  • libxml2 >= 2.7.7
  • +
+

The HPACK tools require the following package:

+
    +
  • jansson >= 2.5
  • +
+

The Python bindings require the following packages:

+
    +
  • cython >= 0.19
  • +
  • python >= 2.7
  • +
+

If you are using Ubuntu 12.04, you need the following packages +installed:

+
    +
  • autoconf
  • +
  • automake
  • +
  • autotools-dev
  • +
  • libtool
  • +
  • pkg-config
  • +
  • zlib1g-dev
  • +
  • libcunit1-dev
  • +
  • libssl-dev
  • +
  • libxml2-dev
  • +
  • libevent-dev
  • +
  • libjansson-dev
  • +
+

spdylay is not packaged in Ubuntu, so you need to build it yourself: +http://tatsuhiro-t.github.io/spdylay/

+
+
+

Build from git¶

+

Building from git is easy, but please be sure that at least autoconf 2.68 is +used:

+
$ autoreconf -i
+$ automake
+$ autoconf
+$ ./configure
+$ make
+
+
+
+

Building documentation¶

+
+

Note

+

Documentation is still incomplete.

+
+

To build documentation, run:

+
$ make html
+
+

The documents will be generated under doc/manual/html/.

+

The generated documents will not be installed with make install.

+

The online documentation is available at +http://tatsuhiro-t.github.io/nghttp2/

+
+
+

Client, Server and Proxy programs¶

+

The src directory contains HTTP/2.0 client, server and proxy programs.

+
+

nghttp - client¶

+

nghttp is a HTTP/2.0 client. It can connect to the HTTP/2.0 server +with prior knowledge, HTTP Upgrade and NPN/ALPN TLS extension.

+

It has verbose output mode for framing information. Here is sample +output from nghttp client:

+
$ src/nghttp -vn https://localhost:8443
+[  0.003] NPN select next protocol: the remote server offers:
+          * HTTP-draft-09/2.0
+          * spdy/3
+          * spdy/2
+          * http/1.1
+          NPN selected the protocol: HTTP-draft-09/2.0
+[  0.005] send SETTINGS frame <length=16, flags=0x00, stream_id=0>
+          (niv=2)
+          [SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
+          [SETTINGS_INITIAL_WINDOW_SIZE(7):65535]
+[  0.006] send HEADERS frame <length=47, flags=0x05, stream_id=1>
+          ; END_STREAM | END_HEADERS
+          ; Open new stream
+          :authority: localhost:8443
+          :method: GET
+          :path: /
+          :scheme: https
+          accept: */*
+          accept-encoding: gzip, deflate
+          user-agent: nghttp2/0.1.0-DEV
+[  0.006] recv SETTINGS frame <length=16, flags=0x00, stream_id=0>
+          (niv=2)
+          [SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
+          [SETTINGS_INITIAL_WINDOW_SIZE(7):65535]
+[  0.006] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
+          ; ACK
+          (niv=0)
+[  0.006] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
+          (window_size_increment=1000000007)
+[  0.006] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
+          ; ACK
+          (niv=0)
+[  0.006] recv HEADERS frame <length=132, flags=0x04, stream_id=1>
+          ; END_HEADERS
+          ; First response header
+          :status: 200
+          accept-ranges: bytes
+          content-encoding: gzip
+          content-length: 146
+          content-type: text/html
+          date: Sun, 27 Oct 2013 14:23:54 GMT
+          etag: "b1-4e5535a027780-gzip"
+          last-modified: Sun, 01 Sep 2013 14:34:22 GMT
+          server: Apache/2.4.6 (Debian)
+          vary: Accept-Encoding
+          via: 1.1 nghttpx
+[  0.006] recv DATA frame <length=146, flags=0x00, stream_id=1>
+[  0.006] recv DATA frame <length=0, flags=0x01, stream_id=1>
+          ; END_STREAM
+[  0.007] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
+          (last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
+
+

The HTTP Upgrade is performed like this:

+
$ src/nghttp -vnu http://localhost:8080
+[  0.000] HTTP Upgrade request
+GET / HTTP/1.1
+Host: localhost:8080
+Connection: Upgrade, HTTP2-Settings
+Upgrade: HTTP-draft-09/2.0
+HTTP2-Settings: AAAABAAAAGQAAAAHAAD__w
+Accept: */*
+User-Agent: nghttp2/0.1.0-DEV
+
+
+[  0.000] HTTP Upgrade response
+HTTP/1.1 101 Switching Protocols
+Connection: Upgrade
+Upgrade: HTTP-draft-09/2.0
+
+
+[  0.001] HTTP Upgrade success
+[  0.001] send SETTINGS frame <length=16, flags=0x00, stream_id=0>
+          (niv=2)
+          [SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
+          [SETTINGS_INITIAL_WINDOW_SIZE(7):65535]
+[  0.001] recv SETTINGS frame <length=16, flags=0x00, stream_id=0>
+          (niv=2)
+          [SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
+          [SETTINGS_INITIAL_WINDOW_SIZE(7):65535]
+[  0.001] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
+          (window_size_increment=1000000007)
+[  0.001] recv HEADERS frame <length=121, flags=0x04, stream_id=1>
+          ; END_HEADERS
+          ; First response header
+          :status: 200
+          accept-ranges: bytes
+          content-length: 177
+          content-type: text/html
+          date: Sun, 27 Oct 2013 14:26:04 GMT
+          etag: "b1-4e5535a027780"
+          last-modified: Sun, 01 Sep 2013 14:34:22 GMT
+          server: Apache/2.4.6 (Debian)
+          vary: Accept-Encoding
+          via: 1.1 nghttpx
+[  0.001] recv DATA frame <length=177, flags=0x00, stream_id=1>
+[  0.001] recv DATA frame <length=0, flags=0x01, stream_id=1>
+          ; END_STREAM
+[  0.001] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
+          ; ACK
+          (niv=0)
+[  0.001] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
+          (last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
+[  0.001] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
+          ; ACK
+          (niv=0)
+
+
+
+

nghttpd - server¶

+

nghttpd is static web server. It is single threaded and +multiplexes connections using non-blocking socket.

+

By default, it uses SSL/TLS connection. Use --no-tls option to +disable it.

+

nghttpd only accept the HTTP/2.0 connection via NPN/ALPN or direct +HTTP/2.0 connection. No HTTP Upgrade is supported.

+

-p option allows users to configure server push.

+

Just like nghttp, it has verbose output mode for framing +information. Here is sample output from nghttpd server:

+
$ src/nghttpd --no-tls -v 8080
+IPv4: listen on port 8080
+IPv6: listen on port 8080
+[id=1] [  1.189] send SETTINGS frame <length=8, flags=0x00, stream_id=0>
+          (niv=1)
+          [SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
+[id=1] [  1.191] recv SETTINGS frame <length=16, flags=0x00, stream_id=0>
+          (niv=2)
+          [SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
+          [SETTINGS_INITIAL_WINDOW_SIZE(7):65535]
+[id=1] [  1.191] recv HEADERS frame <length=47, flags=0x05, stream_id=1>
+          ; END_STREAM | END_HEADERS
+          ; Open new stream
+          :authority: localhost:8080
+          :method: GET
+          :path: /
+          :scheme: http
+          accept: */*
+          accept-encoding: gzip, deflate
+          user-agent: nghttp2/0.1.0-DEV
+[id=1] [  1.192] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
+          ; ACK
+          (niv=0)
+[id=1] [  1.192] send HEADERS frame <length=70, flags=0x04, stream_id=1>
+          ; END_HEADERS
+          ; First response header
+          :status: 404
+          content-encoding: gzip
+          content-type: text/html; charset=UTF-8
+          date: Sun, 27 Oct 2013 14:27:53 GMT
+          server: nghttpd nghttp2/0.1.0-DEV
+[id=1] [  1.192] send DATA frame <length=117, flags=0x00, stream_id=1>
+[id=1] [  1.192] send DATA frame <length=0, flags=0x01, stream_id=1>
+          ; END_STREAM
+[id=1] [  1.192] stream_id=1 closed
+[id=1] [  1.192] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
+          ; ACK
+          (niv=0)
+[id=1] [  1.192] recv GOAWAY frame <length=8, flags=0x00, stream_id=0>
+          (last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
+[id=1] [  1.192] closed
+
+
+
+

nghttpx - proxy¶

+

The nghttpx is a multi-threaded reverse proxy for +HTTP-draft-09/2.0, SPDY and HTTP/1.1. It has several operation modes:

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Mode optionFrontendBackendNote
default modeHTTP/2.0, SPDY, HTTP/1.1 (TLS)HTTP/1.1Reverse proxy
--http2-proxyHTTP/2.0, SPDY, HTTP/1.1 (TLS)HTTP/1.1SPDY proxy
--http2-bridgeHTTP/2.0, SPDY, HTTP/1.1 (TLS)HTTP/2.0 (TLS) 
--clientHTTP/2.0, HTTP/1.1HTTP/2.0 (TLS) 
--client-proxyHTTP/2.0, HTTP/1.1HTTP/2.0 (TLS)Forward proxy
+

The interesting mode at the moment is the default mode. It works like +a reverse proxy and listens HTTP-draft-09/2.0, SPDY and HTTP/1.1 and +can be deployed SSL/TLS terminator for existing web server.

+

The default mode, --http2-proxy and --http2-bridge modes use +SSL/TLS in the frontend connection by default. To disable SSL/TLS, use +--frontend-no-tls option. If that option is used, SPDY is disabled +in the frontend and incoming HTTP/1.1 connection can be upgraded to +HTTP/2.0 through HTTP Upgrade.

+

The --http2-bridge, --client and --client-proxy modes use +SSL/TLS in the backend connection by deafult. To disable SSL/TLS, use +--backend-no-tls option.

+

The nghttpx supports configuration file. See --conf option and +sample configuration file nghttpx.conf.sample.

+

The nghttpx does not support server push.

+

In the default mode, (without any of --http2-proxy, +--http2-bridge, --client-proxy and --client options), +nghttpx works as reverse proxy to the backend server:

+
Client <-- (HTTP/2.0, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Web Server
+                                      [reverse proxy]
+
+
+

With --http2-proxy option, it works as so called secure proxy (aka +SPDY proxy):

+
Client <-- (HTTP/2.0, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Proxy
+                                       [secure proxy]            (e.g., Squid)
+
+
+

The Client in the above is needs to be configured to use +nghttpx as secure proxy.

+

At the time of this writing, Chrome is the only browser which supports +secure proxy. The one way to configure Chrome to use secure proxy is +create proxy.pac script like this:

+
function FindProxyForURL(url, host) {
+    return "HTTPS SERVERADDR:PORT";
+}
+
+
+

SERVERADDR and PORT is the hostname/address and port of the +machine nghttpx is running. Please note that Chrome requires valid +certificate for secure proxy.

+

Then run chrome with the following arguments:

+
$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
+
+

With --http2-bridge, it accepts HTTP/2.0, SPDY and HTTP/1.1 +connections and communicates with backend in HTTP/2.0:

+
Client <-- (HTTP/2.0, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/2.0) --> Web or HTTP/2.0 Proxy etc
+                                                                     (e.g., nghttpx -s)
+
+
+

With --client-proxy option, it works as forward proxy and expects +that the backend is HTTP/2.0 proxy:

+
Client <-- (HTTP/2.0, HTTP/1.1) --> nghttpx <-- (HTTP/2.0) --> HTTP/2.0 Proxy
+                                 [forward proxy]               (e.g., nghttpx -s)
+
+
+

The Client is needs to be configured to use nghttpx as forward +proxy. The frontend HTTP/1.1 connection can be upgraded to HTTP/2.0 +through HTTP Upgrade. With the above configuration, one can use +HTTP/1.1 client to access and test their HTTP/2.0 servers.

+

With --client option, it works as reverse proxy and expects that +the backend is HTTP/2.0 Web server:

+
Client <-- (HTTP/2.0, HTTP/1.1) --> nghttpx <-- (HTTP/2.0) --> Web Server
+                                [reverse proxy]
+
+
+

The frontend HTTP/1.1 connection can be upgraded to HTTP/2.0 +through HTTP Upgrade.

+

For the operation modes which talk to the backend in HTTP/2.0 over +SSL/TLS, the backend connections can be tunneled though HTTP +proxy. The proxy is specified using --backend-http-proxy-uri +option. The following figure illustrates the example of +--http2-bridge and --backend-http-proxy-uri option to talk to +the outside HTTP/2.0 proxy through HTTP proxy:

+
Client <-- (HTTP/2.0, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/2.0) --
+
+        --===================---> HTTP/2.0 Proxy
+          (HTTP proxy tunnel)     (e.g., nghttpx -s)
+
+
+
+
+
+

HPACK tools¶

+

The src directory contains HPACK tools. The deflatehd is +command-line header compression tool. The inflatehd is +command-line header decompression tool. Both tools read input from +stdin and write output to stdout. The errors are written to +stderr. They take JSON as input and output. We use the same JSON data +format used in https://github.com/Jxck/hpack-test-case

+
+

deflatehd - header compressor¶

+

The deflatehd reads JSON data or HTTP/1-style header fields from +stdin and outputs compressed header block in JSON.

+

For the JSON input, the root JSON object must contain context key, +which indicates which compression context is used. If it is +request, request compression context is used. Otherwise, response +compression context is used. The value of cases key contains the +sequence of input header set. They share the same compression context +and are processed in the order they appear. Each item in the sequence +is a JSON object and it must have at least headers key. Its value +is an array of a JSON object containing exactly one name/value pair.

+

Example:

+
{
+  "context": "request",
+  "cases":
+  [
+    {
+      "headers": [
+        { ":method": "GET" },
+        { ":path": "/" }
+      ]
+    },
+    {
+      "headers": [
+        { ":method": "POST" },
+        { ":path": "/" }
+      ]
+    }
+  ]
+}
+
+
+

With -t option, the program can accept more familiar HTTP/1 style +header field block. Each header set is delimited by empty line:

+

Example:

+
:method: GET
+:scheme: https
+:path: /
+
+:method: POST
+user-agent: nghttp2
+
+
+

The output is JSON object. It contains context key and its value +is request if the compression context is request, otherwise +response. The root JSON object also contains cases key and its +value is an array of JSON object, which has at least following keys:

+
+
seq
+
The index of header set in the input.
+
input_length
+
The sum of length of name/value pair in the input.
+
output_length
+
The length of compressed header block.
+
percentage_of_original_size
+
input_length / output_length * 100
+
wire
+
The compressed header block in hex string.
+
headers
+
The input header set.
+
header_table_size
+
The header table size adjsuted before deflating header set.
+
+

Examples:

+
{
+  "context": "request",
+  "cases":
+  [
+    {
+      "seq": 0,
+      "input_length": 66,
+      "output_length": 20,
+      "percentage_of_original_size": 30.303030303030305,
+      "wire": "01881f3468e5891afcbf83868a3d856659c62e3f",
+      "headers": [
+        {
+          ":authority": "example.org"
+        },
+        {
+          ":method": "GET"
+        },
+        {
+          ":path": "/"
+        },
+        {
+          ":scheme": "https"
+        },
+        {
+          "user-agent": "nghttp2"
+        }
+      ],
+      "header_table_size": 4096
+    }
+    ,
+    {
+      "seq": 1,
+      "input_length": 74,
+      "output_length": 10,
+      "percentage_of_original_size": 13.513513513513514,
+      "wire": "88448504252dd5918485",
+      "headers": [
+        {
+          ":authority": "example.org"
+        },
+        {
+          ":method": "POST"
+        },
+        {
+          ":path": "/account"
+        },
+        {
+          ":scheme": "https"
+        },
+        {
+          "user-agent": "nghttp2"
+        }
+      ],
+      "header_table_size": 4096
+    }
+  ]
+}
+
+
+

The output can be used as the input for inflatehd and +deflatehd.

+

With -d option, the extra header_table key is added and its +associated value contains the state of dyanmic header table after the +corresponding header set was processed. The value contains following +keys:

+
+
entries
+
The entry in the header table. If referenced is true, it +is in the reference set. The size includes the overhead (32 +bytes). The index corresponds to the index of header table. +The name is the header field name and the value is the +header field value. They may be displayed as **DEALLOCATED**, +which means that the memory for that string is freed and not +available. This will happen when the specifying smaller value in +-S than -s.
+
size
+
The sum of the spaces entries occupied, this includes the +entry overhead.
+
max_size
+
The maximum header table size.
+
deflate_size
+
The sum of the spaces entries occupied within +max_deflate_size.
+
max_deflate_size
+
The maximum header table size encoder uses. This can be smaller +than max_size. In this case, encoder only uses up to first +max_deflate_size buffer. Since the header table size is still +max_size, the encoder has to keep track of entries ouside the +max_deflate_size but inside the max_size and make sure +that they are no longer referenced.
+
+

Example:

+
{
+  "context": "request",
+  "cases":
+  [
+    {
+      "seq": 0,
+      "input_length": 66,
+      "output_length": 20,
+      "percentage_of_original_size": 30.303030303030305,
+      "wire": "01881f3468e5891afcbf83868a3d856659c62e3f",
+      "headers": [
+        {
+          ":authority": "example.org"
+        },
+        {
+          ":method": "GET"
+        },
+        {
+          ":path": "/"
+        },
+        {
+          ":scheme": "https"
+        },
+        {
+          "user-agent": "nghttp2"
+        }
+      ],
+      "header_table_size": 4096,
+      "header_table": {
+        "entries": [
+          {
+            "index": 1,
+            "name": "user-agent",
+            "value": "nghttp2",
+            "referenced": true,
+            "size": 49
+          },
+          {
+            "index": 2,
+            "name": ":scheme",
+            "value": "https",
+            "referenced": true,
+            "size": 44
+          },
+          {
+            "index": 3,
+            "name": ":path",
+            "value": "/",
+            "referenced": true,
+            "size": 38
+          },
+          {
+            "index": 4,
+            "name": ":method",
+            "value": "GET",
+            "referenced": true,
+            "size": 42
+          },
+          {
+            "index": 5,
+            "name": ":authority",
+            "value": "example.org",
+            "referenced": true,
+            "size": 53
+          }
+        ],
+        "size": 226,
+        "max_size": 4096,
+        "deflate_size": 226,
+        "max_deflate_size": 4096
+      }
+    }
+    ,
+    {
+      "seq": 1,
+      "input_length": 74,
+      "output_length": 10,
+      "percentage_of_original_size": 13.513513513513514,
+      "wire": "88448504252dd5918485",
+      "headers": [
+        {
+          ":authority": "example.org"
+        },
+        {
+          ":method": "POST"
+        },
+        {
+          ":path": "/account"
+        },
+        {
+          ":scheme": "https"
+        },
+        {
+          "user-agent": "nghttp2"
+        }
+      ],
+      "header_table_size": 4096,
+      "header_table": {
+        "entries": [
+          {
+            "index": 1,
+            "name": ":method",
+            "value": "POST",
+            "referenced": true,
+            "size": 43
+          },
+          {
+            "index": 2,
+            "name": "user-agent",
+            "value": "nghttp2",
+            "referenced": true,
+            "size": 49
+          },
+          {
+            "index": 3,
+            "name": ":scheme",
+            "value": "https",
+            "referenced": true,
+            "size": 44
+          },
+          {
+            "index": 4,
+            "name": ":path",
+            "value": "/",
+            "referenced": false,
+            "size": 38
+          },
+          {
+            "index": 5,
+            "name": ":method",
+            "value": "GET",
+            "referenced": false,
+            "size": 42
+          },
+          {
+            "index": 6,
+            "name": ":authority",
+            "value": "example.org",
+            "referenced": true,
+            "size": 53
+          }
+        ],
+        "size": 269,
+        "max_size": 4096,
+        "deflate_size": 269,
+        "max_deflate_size": 4096
+      }
+    }
+  ]
+}
+
+
+
+
+

inflatehd - header decompressor¶

+

The inflatehd reads JSON data from stdin and outputs decompressed +name/value pairs in JSON.

+

The root JSON object must contain context key, which indicates +which compression context is used. If it is request, request +compression context is used. Otherwise, response compression context +is used. The value of cases key contains the sequence of +compressed header block. They share the same compression context and +are processed in the order they appear. Each item in the sequence is a +JSON object and it must have at least wire key. Its value is a +string containing compressed header block in hex string.

+

Example:

+
{
+  "context": "request",
+  "cases":
+  [
+    { "wire": "8285" },
+    { "wire": "8583" }
+  ]
+}
+
+
+

The output is JSON object. It contains context key and its value +is request if the compression context is request, otherwise +response. The root JSON object also contains cases key and its +value is an array of JSON object, which has at least following keys:

+
+
seq
+
The index of header set in the input.
+
headers
+
The JSON array contains decompressed name/value pairs.
+
wire
+
The compressed header block in hex string.
+
header_table_size
+
The header table size adjsuted before inflating compressed header +block.
+
+

Example:

+
{
+  "context": "request",
+  "cases":
+  [
+    {
+      "seq": 0,
+      "wire": "01881f3468e5891afcbf83868a3d856659c62e3f",
+      "headers": [
+        {
+          ":authority": "example.org"
+        },
+        {
+          ":method": "GET"
+        },
+        {
+          ":path": "/"
+        },
+        {
+          ":scheme": "https"
+        },
+        {
+          "user-agent": "nghttp2"
+        }
+      ],
+      "header_table_size": 4096
+    }
+    ,
+    {
+      "seq": 1,
+      "wire": "88448504252dd5918485",
+      "headers": [
+        {
+          ":method": "POST"
+        },
+        {
+          ":path": "/account"
+        },
+        {
+          "user-agent": "nghttp2"
+        },
+        {
+          ":scheme": "https"
+        },
+        {
+          ":authority": "example.org"
+        }
+      ],
+      "header_table_size": 4096
+    }
+  ]
+}
+
+
+

The output can be used as the input for deflatehd and +inflatehd.

+

With -d option, the extra header_table key is added and its +associated value contains the state of dyanmic header table after the +corresponding header set was processed. The format is the same as +deflatehd.

+
+
+
+

Python bindings¶

+

This python directory contains nghttp2 Python bindings. The +bindings currently only provide HPACK compressor and decompressor +classes.

+

The extension module is called nghttp2.

+

make will build the bindings and target Python version is +determined by configure script. If the detected Python version is not +what you expect, specify a path to Python executable in PYTHON +variable as an argument to configure script (e.g., ./configure +PYTHON=/usr/bin/python3.3).

+
+

Example¶

+

The following example code illustrates basic usage of HPACK compressor +and decompressor in Python:

+
import binascii
+import nghttp2
+
+deflater = nghttp2.HDDeflater(nghttp2.HD_SIDE_REQUEST)
+inflater = nghttp2.HDInflater(nghttp2.HD_SIDE_REQUEST)
+
+data = deflater.deflate([(b'foo', b'bar'),
+                         (b'baz', b'buz')])
+print(binascii.b2a_hex(data))
+
+hdrs = inflater.inflate(data)
+print(hdrs)
+
+
+
+
+
+ + +
+ +
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/released-versions/v0.3.0/search.html b/released-versions/v0.3.0/search.html new file mode 100644 index 00000000..93a5a7e2 --- /dev/null +++ b/released-versions/v0.3.0/search.html @@ -0,0 +1,191 @@ + + + + + + + + + + Search — nghttp2 0.3.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+
    +
  • Docs »
  • + +
  • +
  • + +
  • +
+
+
+
+ + + + +
+ +
+ +
+ +
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/released-versions/v0.3.0/searchindex.js b/released-versions/v0.3.0/searchindex.js new file mode 100644 index 00000000..e5aab890 --- /dev/null +++ b/released-versions/v0.3.0/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({objects:{"":{NGHTTP2_ERR_INVALID_STATE:[3,1,1,""],NGHTTP2_ERR_HEADER_COMP:[3,1,1,""],NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:[3,1,1,""],nghttp2_settings_entry:[3,2,1,""],NGHTTP2_INTERNAL_ERROR:[3,1,1,""],NGHTTP2_PRI_LOWEST:[3,1,1,""],nghttp2_on_frame_recv_callback:[3,2,1,""],NGHTTP2_CLIENT_CONNECTION_HEADER_LEN:[3,1,1,""],nghttp2_goaway:[3,2,1,""],nghttp2_ping:[3,2,1,""],NGHTTP2_ERR_INVALID_FRAME:[3,1,1,""],nghttp2_frame_type:[3,2,1,""],NGHTTP2_ERR_INVALID_STREAM_ID:[3,1,1,""],nghttp2_select_next_protocol:[3,3,1,""],NGHTTP2_ERR_INVALID_HEADER_BLOCK:[3,1,1,""],nghttp2_session_callbacks:[3,2,1,""],NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS:[3,1,1,""],NGHTTP2_ERR_PROTO:[3,1,1,""],NGHTTP2_MAX_HEADER_TABLE_SIZE:[3,1,1,""],nghttp2_submit_window_update:[3,3,1,""],NGHTTP2_ERR_UNSUPPORTED_VERSION:[3,1,1,""],NGHTTP2_SETTINGS_ENABLE_PUSH:[3,1,1,""],nghttp2_window_update:[3,2,1,""],nghttp2_session_client_new2:[3,3,1,""],NGHTTP2_DATA:[3,1,1,""],nghttp2_frame_hd:[3,2,1,""],NGHTTP2_ERR_INVALID_STREAM_STATE:[3,1,1,""],nghttp2_on_header_callback:[3,2,1,""],NGHTTP2_FLAG_ACK:[3,1,1,""],NGHTTP2_STREAM_CLOSED:[3,1,1,""],NGHTTP2_SETTINGS_MAX:[3,1,1,""],NGHTTP2_MAX_WINDOW_SIZE:[3,1,1,""],nghttp2_headers_category:[3,2,1,""],nghttp2_error_code:[3,2,1,""],NGHTTP2_REFUSED_STREAM:[3,1,1,""],nghttp2_on_data_chunk_recv_callback:[3,2,1,""],NGHTTP2_ERR_START_STREAM_NOT_ALLOWED:[3,1,1,""],NGHTTP2_ERR_FLOW_CONTROL:[3,1,1,""],nghttp2_strerror:[3,3,1,""],nghttp2_gzip_inflate_del:[3,3,1,""],NGHTTP2_ERR_FATAL:[3,1,1,""],nghttp2_submit_goaway:[3,3,1,""],nghttp2_error:[3,2,1,""],NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE:[3,1,1,""],NGHTTP2_ERR_NOMEM:[3,1,1,""],NGHTTP2_ERR_PAUSE:[3,1,1,""],NGHTTP2_ENHANCE_YOUR_CALM:[3,1,1,""],NGHTTP2_NO_ERROR:[3,1,1,""],NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS:[3,1,1,""],nghttp2_session_server_new2:[3,3,1,""],NGHTTP2_ERR_DEFERRED:[3,1,1,""],nghttp2_push_promise:[3,2,1,""],NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE:[3,1,1,""],nghttp2_session_get_outbound_queue_size:[3,3,1,""],nghttp2_rst_stream:[3,2,1,""],NGHTTP2_PROTO_VERSION_ID_LEN:[3,1,1,""],NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS:[3,1,1,""],nghttp2_data_source_read_callback:[3,2,1,""],NGHTTP2_SETTINGS_TIMEOUT:[3,1,1,""],NGHTTP2_ERR_WOULDBLOCK:[3,1,1,""],nghttp2_session_resume_data:[3,3,1,""],NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:[3,1,1,""],NGHTTP2_PRI_DEFAULT:[3,1,1,""],nghttp2_session_server_new:[3,3,1,""],NGHTTP2_CONTINUATION:[3,1,1,""],NGHTTP2_FLAG_END_PUSH_PROMISE:[3,1,1,""],NGHTTP2_ERR_INVALID_ARGUMENT:[3,1,1,""],NGHTTP2_ERR_FRAME_SIZE_ERROR:[3,1,1,""],nghttp2_session_del:[3,3,1,""],nghttp2_session_mem_recv:[3,3,1,""],nghttp2_flag:[3,2,1,""],NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE:[3,1,1,""],NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:[3,1,1,""],NGHTTP2_HCAT_REQUEST:[3,1,1,""],NGHTTP2_FLAG_END_HEADERS:[3,1,1,""],nghttp2_gzip:[3,2,1,""],NGHTTP2_FLAG_END_STREAM:[3,1,1,""],NGHTTP2_ERR_EOF:[3,1,1,""],NGHTTP2_HCAT_HEADERS:[3,1,1,""],NGHTTP2_VERSION_NUM:[3,1,1,""],NGHTTP2_SETTINGS:[3,1,1,""],nghttp2_frame:[3,2,1,""],nghttp2_submit_push_promise:[3,3,1,""],NGHTTP2_ERR_DEFERRED_DATA_EXIST:[3,1,1,""],NGHTTP2_CANCEL:[3,1,1,""],nghttp2_send_callback:[3,2,1,""],nghttp2_on_frame_send_callback:[3,2,1,""],NGHTTP2_HEADERS:[3,1,1,""],NGHTTP2_VERSION:[3,1,1,""],nghttp2_opt_set:[3,2,1,""],nghttp2_session:[3,2,1,""],NGHTTP2_COMPRESSION_ERROR:[3,1,1,""],NGHTTP2_HCAT_PUSH_RESPONSE:[3,1,1,""],nghttp2_submit_rst_stream:[3,3,1,""],nghttp2_submit_headers:[3,3,1,""],nghttp2_recv_callback:[3,2,1,""],nghttp2_session_get_stream_user_data:[3,3,1,""],NGHTTP2_FLAG_PRIORITY:[3,1,1,""],nghttp2_nv:[3,2,1,""],nghttp2_on_invalid_frame_recv_callback:[3,2,1,""],nghttp2_version:[3,3,1,""],nghttp2_on_unknown_frame_recv_callback:[3,2,1,""],NGHTTP2_ERR_STREAM_CLOSED:[3,1,1,""],nghttp2_opt:[3,2,1,""],NGHTTP2_ERR_CALLBACK_FAILURE:[3,1,1,""],NGHTTP2_ERR_GOAWAY_ALREADY_SENT:[3,1,1,""],NGHTTP2_FLOW_CONTROL_ERROR:[3,1,1,""],nghttp2_session_set_stream_user_data:[3,3,1,""],nghttp2_check_header_value:[3,3,1,""],NGHTTP2_ERR_STREAM_CLOSING:[3,1,1,""],nghttp2_session_client_new:[3,3,1,""],nghttp2_check_header_name:[3,3,1,""],nghttp2_info:[3,2,1,""],NGHTTP2_PROTO_VERSION_ID:[3,1,1,""],nghttp2_settings_id:[3,2,1,""],nghttp2_session_send:[3,3,1,""],NGHTTP2_PROTOCOL_ERROR:[3,1,1,""],nghttp2_gzip_inflate:[3,3,1,""],nghttp2_session_upgrade:[3,3,1,""],nghttp2_on_begin_headers_callback:[3,2,1,""],NGHTTP2_ERR_INSUFF_BUFSIZE:[3,1,1,""],nghttp2_settings:[3,2,1,""],nghttp2_on_frame_not_send_callback:[3,2,1,""],nghttp2_session_get_effective_recv_data_length:[3,3,1,""],nghttp2_submit_data:[3,3,1,""],nghttp2_submit_response:[3,3,1,""],NGHTTP2_CLIENT_CONNECTION_HEADER:[3,1,1,""],NGHTTP2_FLAG_NONE:[3,1,1,""],nghttp2_session_terminate_session:[3,3,1,""],nghttp2_submit_settings:[3,3,1,""],NGHTTP2_HCAT_RESPONSE:[3,1,1,""],NGHTTP2_PING:[3,1,1,""],NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE:[3,1,1,""],nghttp2_priority:[3,2,1,""],nghttp2_session_want_read:[3,3,1,""],NGHTTP2_VERSION_AGE:[3,1,1,""],NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE:[3,1,1,""],NGHTTP2_CONNECT_ERROR:[3,1,1,""],NGHTTP2_RST_STREAM:[3,1,1,""],nghttp2_on_stream_close_callback:[3,2,1,""],NGHTTP2_PUSH_PROMISE:[3,1,1,""],nghttp2_data_provider:[3,2,1,""],NGHTTP2_ERR_PUSH_DISABLED:[3,1,1,""],nghttp2_session_recv:[3,3,1,""],nghttp2_session_get_effective_local_window_size:[3,3,1,""],NGHTTP2_INITIAL_WINDOW_SIZE:[3,1,1,""],NGHTTP2_WINDOW_UPDATE:[3,1,1,""],NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS:[3,1,1,""],nghttp2_session_want_write:[3,3,1,""],nghttp2_submit_priority:[3,3,1,""],nghttp2_session_get_stream_effective_local_window_size:[3,3,1,""],nghttp2_headers:[3,2,1,""],nghttp2_before_frame_send_callback:[3,2,1,""],NGHTTP2_GOAWAY:[3,1,1,""],NGHTTP2_ERR_GZIP:[3,1,1,""],nghttp2_is_fatal:[3,3,1,""],nghttp2_submit_ping:[3,3,1,""],NGHTTP2_FRAME_SIZE_ERROR:[3,1,1,""],nghttp2_data_source:[3,2,1,""],NGHTTP2_ERR_STREAM_SHUT_WR:[3,1,1,""],NGHTTP2_PRIORITY:[3,1,1,""],nghttp2_submit_request:[3,3,1,""],nghttp2_session_get_stream_effective_recv_data_length:[3,3,1,""],nghttp2_pack_settings_payload:[3,3,1,""],nghttp2_data:[3,2,1,""],nghttp2_gzip_inflate_new:[3,3,1,""],nghttp2_nv_compare_name:[3,3,1,""]},nghttp2_session_callbacks:{on_invalid_frame_recv_callback:[3,0,1,""],before_frame_send_callback:[3,0,1,""],on_stream_close_callback:[3,0,1,""],on_data_chunk_recv_callback:[3,0,1,""],on_begin_headers_callback:[3,0,1,""],send_callback:[3,0,1,""],on_unknown_frame_recv_callback:[3,0,1,""],on_frame_recv_callback:[3,0,1,""],on_header_callback:[3,0,1,""],on_frame_not_send_callback:[3,0,1,""],on_frame_send_callback:[3,0,1,""],recv_callback:[3,0,1,""]},nghttp2_frame:{push_promise:[3,0,1,""],settings:[3,0,1,""],ping:[3,0,1,""],rst_stream:[3,0,1,""],priority:[3,0,1,""],headers:[3,0,1,""],goaway:[3,0,1,""],window_update:[3,0,1,""],data:[3,0,1,""],hd:[3,0,1,""]},nghttp2_ping:{hd:[3,0,1,""]},nghttp2_data_provider:{source:[3,0,1,""],read_callback:[3,0,1,""]},nghttp2_priority:{pri:[3,0,1,""],hd:[3,0,1,""]},nghttp2_settings_entry:{settings_id:[3,0,1,""],value:[3,0,1,""]},nghttp2_window_update:{hd:[3,0,1,""],window_size_increment:[3,0,1,""]},nghttp2_frame_hd:{stream_id:[3,0,1,""],length:[3,0,1,""],flags:[3,0,1,""],type:[3,0,1,""]},nghttp2_info:{age:[3,0,1,""],version_str:[3,0,1,""],version_num:[3,0,1,""],proto_str:[3,0,1,""]},nghttp2_rst_stream:{error_code:[3,0,1,""],hd:[3,0,1,""]},nghttp2_nv:{valuelen:[3,0,1,""],namelen:[3,0,1,""],name:[3,0,1,""],value:[3,0,1,""]},nghttp2_headers:{nvlen:[3,0,1,""],pri:[3,0,1,""],hd:[3,0,1,""],nva:[3,0,1,""],cat:[3,0,1,""]},nghttp2_opt_set:{no_auto_stream_window_update:[3,0,1,""],peer_max_concurrent_streams:[3,0,1,""],no_auto_connection_window_update:[3,0,1,""]},nghttp2_goaway:{opaque_data:[3,0,1,""],error_code:[3,0,1,""],opaque_data_len:[3,0,1,""],hd:[3,0,1,""],last_stream_id:[3,0,1,""]},nghttp2_data_source:{fd:[3,0,1,""],ptr:[3,0,1,""]},nghttp2_push_promise:{promised_stream_id:[3,0,1,""],nvlen:[3,0,1,""],nva:[3,0,1,""],hd:[3,0,1,""]},nghttp2_settings:{niv:[3,0,1,""],hd:[3,0,1,""],iv:[3,0,1,""]}},terms:{my_obj:[3,6],nghttp2_io_flag:6,nghttp2_cancel:[3,6],opt_set:[3,6],prefix:[2,6,3],nghttp2_session_get_stream_effective_local_window_s:[3,6],"const":[2,6,5,3],nghttp2_submit_:[2,5],under:[3,6,4],bufferevent_getfd:5,spec:[3,6],merchant:[2,6,5,1],digit:5,"void":[2,6,5,3],bufferevent_ssl:[2,5],initialize_nghttp2_setup:[2,5],verif:5,servic:2,warnx:[2,5],on_stream_close_callback:[2,6,5,3],direct:4,ssl_op_no_session_resumption_on_renegoti:[2,5],neg:[3,6],nghttp2_err_insuff_bufs:[3,6],"new":[2,6,4,5,3],tatsuhiro:[0,1,2,4,5,6],nghttp2_session_resume_data:[3,6],ipproto_tcp:[2,5],abov:[2,1,3,4,5,6],initialize_app_context:2,here:[2,6,4,5,3],met:[2,6,5,3],path:[2,4,5],settings_timeout:[3,6],interpret:[3,6],nextprotoneg:[3,6],sslv23_server_method:2,permit:[2,6,5,1],nghttp2_submit_prior:[3,6],aka:[3,6,4],nghttp2_err_gzip:[3,6],nghttp2_frame:[2,6,5,3],bufferevent_ssl_connect:5,substr:2,bev_event_error:[2,5],printabl:5,unit:4,describ:[2,6,5,3],would:[3,6],overhead:4,asset:4,nghttp2_on_invalid_frame_recv_callback:[3,6],nghttp2_version:[3,6,1],type:[0,2,3,4,5,6],tell:[2,6,5,3],relat:[2,5],notic:[2,6,5,1],warn:2,ssl_shutdown:[2,5],herebi:[2,6,5,1],unpack:[3,6],must:[2,6,4,5,3],word:[3,6],err:[2,5],exit_failur:[2,5],setup:[2,5],work:[2,4],lev_opt_close_on_fre:2,nghttp2_flag_ack:[3,6],root:[2,4],syn_repli:[3,6],defer:[2,6,5,3],give:[3,6],indic:[2,6,4,5,3],want:[2,6,5,3],unsign:[2,6,5,3],nghttp2_settings_flow_control_opt:[3,6],end:[2,6,5,3],datalen:[2,5],how:5,nghttp2_err_fat:[3,6],nghttp2_frame_typ:[3,6],updat:[3,6],nghttp2_msg_more:6,after:[2,6,4,5,3],badli:[3,6],demonstr:5,request_path:2,attempt:[3,6],third:[2,6,5,3],opaqu:[3,6],exclud:[3,6],receiv:[2,6,5,3],first:[2,6,4,5,3],order:[2,6,4,3],frontend:4,over:[2,4,5],becaus:[2,6,5,3],eagain:[2,5],vari:4,fit:[2,6,5,1],fwrite:5,deflate_s:4,hidden:[3,6],them:[2,6,5,3],thei:[2,6,4,5,3],safe:[2,6,3],"break":[2,6,5,3],promis:[3,6],choic:[3,6],ai_addr:2,timeout:[2,5],each:[2,6,4,5,3],debug:[3,6,5],side:[2,6,3],mean:[3,6,4,5],slen:2,protocol_error:[3,6],http2_stream_data:[2,5],nghttp2_session_server_new2:[3,6],network:[2,5],content:[0,4,2],end_stream:[3,6,4],situat:[2,5],free:[2,6,5,1,3],spdy:[3,6,4],openssl:[2,4,5],nghttp2_version_num:[3,6,1],sigact:[2,5],rang:[3,6,4],restrict:[2,6,5,1],nghttp2_protocol_error:[3,6],alreadi:[2,6,5,3],primari:[3,6],nghttp2_max_header_table_s:[3,6],too:[2,6,3],memcmp:2,draft:[0,6,4,3],listen:[2,4],tool:[0,6,4,3],travers:2,compressor:4,target:[3,6,4],provid:[2,1,3,4,5,6],project:[0,4],matter:[3,6],nghttp2_continu:[3,6],increment:[3,6],nghttp2_session_recv:[3,6],nghttp2_session_get_stream_effective_recv_data_length:[3,6],transmit:[3,6,5],sig_ign:[2,5],shall:[2,6,5,1],object:[2,6,4,5,3],writecb:[2,5],nghttp2_settings_timeout:[3,6],simplic:5,don:[2,6,3],hex_to_uint:2,doc:4,flow:[3,6],doe:[2,6,4,5,3],nghttp2_gzip_inflate_new:[3,6],section:[3,6],on_invalid_frame_recv_callback:[3,6],bev_event_eof:[2,5],pkg:4,identifi:[2,6,5,3],bufferevent_setcb:[2,5],involv:[3,6],explain:5,configur:[3,6,4],apach:4,nghttp2_err_invalid_stream_id:[3,6],busi:[2,5],oct:4,nghttp2_err_proto:[3,6],authoritylen:5,stop:[2,5],end_head:[3,6,4],evbuffer_drain:[2,5],bar:4,ai_pass:2,ietf:[0,6,4,3],baz:4,push_promis:[2,6,3],"public":[0,6,4,3],nghttp2_strerror:[2,6,5,3],nghttp2_gzip_inflate_del:[3,6],bufferevent_ssl_accept:2,nul:[3,6],result:[2,6,5,3],respons:[2,6,4,5,3],fail:[3,6],key_fil:2,subject:[2,6,5,1],said:[3,6],figur:4,bev_opt_close_on_fre:[2,5],accord:[3,6],extens:[4,5],advertis:[2,5],setsockopt:[2,5],against:[3,6],ssl_ctx_use_certificate_chain_fil:2,header_t:4,logic:2,enhance_your_calm:[3,6],com:[0,6,4,3],int32_t:[2,6,5,3],assum:[3,6],duplic:[3,6],reciev:5,liabil:[2,6,5,1],evbuffer_get_length:[2,5],union:[0,6,3,2],max_deflate_s:4,been:[2,6,5,3],trigger:[3,6],interest:[2,4,5],basic:4,futur:[3,6],tini:5,life:2,regul:[2,5],argument:[2,6,4,5,3],ewouldblock:[2,5],ssl_op_no_compress:[2,5],nghttp2_settings_initial_window_s:[3,6],zlib:4,nghttp2_on_begin_headers_callback:[3,6,5],bev_event_timeout:[2,5],bufferevent_socket_connect_hostnam:5,nghttp2_set:[3,6],promised_stream_id:[3,6],conf:4,sever:[2,6,4,5,3],perform:[2,6,4,3],make:[2,6,4,3],transpar:[3,6],headlen:[3,6],split:[3,6],version_str:[3,6],nghttp2_on_stream_close_callback:[3,6,5],complet:[2,6,5,3],start_listen:2,bufferevent_openssl_get_ssl:[2,5],nghttp2_err_deferred_data_exist:[3,6],ssl_ctx_new:[2,5],zlib1g:4,ownership:[3,6],niv:[3,6,4],thu:[2,6,3],nghttp2_session_get_effective_local_window_s:[3,6],client:[0,2,3,4,5,6],thi:[0,1,2,3,4,5,6],endif:[2,6,1],gzip:[3,6,4],opaque_data:[3,6,4],protocol:[0,2,3,4,5,6],just:[2,6,4,5,3],"0x01":4,initiate_connect:5,ifdef:[2,6],previous:[3,6],easi:4,els:[2,5],applic:[2,6,4,5,3],initialize_nghttp2_sess:[2,5],specif:[2,6,5,3],arbitrari:[3,6],http2_session_data:[2,5],client_addr:2,manual:4,html:[0,6,4,3,2],tcp_nodelai:[2,5],unnecessari:5,underli:[2,5],www:[3,6],right:[2,6,5,1],deal:[2,6,5,1,3],intern:[3,6],successfulli:[2,6,5,3],transmiss:[2,6,5,3],ni_numerichost:2,bottom:[3,6],nghttp2_data_source_read_callback:[3,6],buffer:[2,6,4,5,3],condit:[2,6,5,1,3],foo:4,localhost:4,particular:[2,6,5,1,3],sensibl:[3,6],repositori:[2,5],peer:[2,6,5,3],post:[3,6,4],decompressor:4,inlen_ptr:[3,6],nghttp2_submit_data:[3,6],nghttp2_settings_max_concurrent_stream:[2,6,5,3],produc:[3,6],evbuff:[2,5],encod:[2,6,4,3],down:[2,5],nghttp2_before_frame_send_callback:[3,6,5],errx:[2,5],git:[0,6,4,3],session_send:[2,5],wai:[3,6,4],support:[2,6,4,5,3],verbos:4,call:[2,6,4,5,3],fork:4,head:[2,6,3],form:[3,6],offer:4,bev_event_connect:[2,5],"true":4,hddeflat:4,ssl_ctx_free:[2,5],maximum:[3,6,4],until:[3,6],deafult:4,autoconf:4,emit:[2,6,5,3],nghttp2_initial_window_s:[3,6],featur:4,httpbi:[0,6,4,3],"abstract":[2,5],unreleas:4,exist:[3,6,4],ai_flag:2,ends_with:2,check:[2,6,5,3],delete_http2_session_data:[2,5],when:[2,6,4,5,3],role:[2,6,5,3],nghttp2_check_header_valu:[3,6],send_client_connection_head:5,unlimit:[3,6],intend:2,af_unspec:[2,5],nghttp2_max_window_s:[3,6],technot:[3,6],max_siz:4,evconnlistener_new_bind:2,longer:[2,4],nghttp2_check_header_nam:[3,6],ignor:[2,6,3],time:[2,6,4,3],push:[3,6,4],skip:[3,6],evbuffer_remov:2,nghttp2_on_frame_recv_callback:[3,6,5],nghttp2ver_h:1,decid:[3,6],create_ssl_ctx:[2,5],depend:[2,5],readabl:5,sourc:[0,6,5,3,2],string:[2,6,4,5,3],nghttp2_settings_enable_push:[3,6],level:[2,6,3],did:[3,6,5],item:4,settings_id:[3,6],conhead:2,upper:[3,6],sign:4,port:[2,4,5],appear:[3,6,4],event_base_fre:[2,5],current:[2,6,4,3],gener:[3,6,4],address:4,nghttp2_submit_rst_stream:[2,6,3],connect_error:[3,6],queue:[2,6,5,3],behav:[3,6],ourselv:[2,5],nghttp2_err_goaway_already_s:[3,6],regardless:[3,6],extra:[4,5],modul:4,prefer:[3,6],instal:4,hdinflat:4,memori:[2,6,4,5,3],strdup:2,prev:2,reorder:[3,6,5],rst_stream:[2,6,5,3],ctype:2,nghttp2_submit_window_upd:[3,6],prepar:[3,6],stream_user_data:[3,6,5],cat:[2,6,5,3],descriptor:[2,6,3],can:[2,6,4,5,3],http2:[0,6,4,3],purpos:[2,6,5,1],uf_path:5,claim:[2,6,5,1],stream:[2,6,4,5,3],agent:4,critic:[3,6],abort:[3,6],tabl:[3,6,4],nghttp2_header:[2,6,5,3],occur:[3,6],alwai:[2,6,3],multipl:[2,6,5,3],charset:4,ping:[3,6],write:[2,4,5],opt_set_mask:[3,6],max:5,intrus:2,mai:[2,6,4,5,3],acceptcb:2,data:[2,6,4,5,3],autotool:4,stdin:4,inform:[2,6,4,5,3],"switch":[2,4,5],aaaabaaaagqaaaahaad__w:4,talk:[2,4],nghttp2_err_stream_shut_wr:[3,6],size_t:[2,6,5,3],nghttp2_err_unsupported_vers:[3,6],still:[2,6,4,3],pointer:[2,6,3],entiti:2,disconnect:[2,5],precondit:[3,6],tort:[2,6,5,1],window:[3,6],main:[2,5],non:[2,6,4,5,3],recal:5,initi:[2,6,5,3],nghttp2_submit_head:[3,6],nghttp2_on_header_callback:[2,6,5,3],name:[2,6,4,5,3],version_num:[3,6],config:4,no_error:4,drop:[2,6,5,3],replac:[3,6],individu:[3,6],continu:[2,6,4,5,3],event_base_loop:[2,5],turoti:5,happen:[2,4,5],ai_addrlen:2,space:[3,6,4],output_length:4,nghttp2_flag_end_push_promis:[3,6],earlier:[2,4,5],event_base_new:[2,5],argv:[2,5],org:[0,6,4,3],"byte":[2,6,4,5,3],argc:[2,5],care:[3,6],nghttp2_opt_no_auto_connection_window_upd:[3,6],nghttp2ver:[0,6,1,3],"88448504252dd5918485":4,befor:[2,6,4,5,3],thing:[2,6,5,3],nghttp2_flag_non:[2,6,5,3],place:[3,6],evdns_base_new:5,oper:[3,6,4],directli:[2,6,5,3],onc:[3,6],arrai:[3,6,4,5],yourself:4,nghttp2_is_fat:[3,6],nghttp2_flow_control_error:[3,6],submit:[3,6,5],on_frame_recv_callback:[2,6,5,3],open:[2,6,4,3],size:[2,6,4,3],avail:[2,6,4,5,3],given:[3,6],necessarili:[3,6],sigpip:[2,5],internal_error:[3,6],conveni:[3,6],ssl_ctx:[2,6,5,3],copi:[2,6,5,1,3],specifi:[2,6,4,5,3],github:[0,4],holder:[2,6,5,1],than:[2,6,4,3],serv:2,wide:2,nghttp2_session_get_outbound_queue_s:[3,6],were:[2,5],posit:[3,6],read_callback:[2,6,3],browser:4,lowest:[3,6],sai:[3,6],pri:[3,6],ani:[2,1,3,4,5,6],deliv:[3,6],bitwis:[3,6],event_bas:[2,5],nghttp2_flag_prior:[3,6],destroi:[2,5],payloadlen:[3,6],note:[2,6,4,5,3],take:[2,6,4,5,3],properti:[2,5],noth:[3,6],begin:5,sure:[2,4,5],normal:[3,6],track:[2,4,5],compress:[0,4],nghttp2_hcat_request:[2,6,5,3],pathlen:5,sublicens:[2,6,5,1],pair:[2,6,4,5,3],http2_select:[3,6],later:[2,6,5,3],gracefulli:5,show:[4,5],unprocess:[2,5],concurr:[2,6,3],permiss:[2,6,5,1],threshold:2,onli:[2,6,4,5,3],state:[2,6,4,3],"4e5535a027780":4,overwritten:[3,6],reset:5,variou:[3,6],get:[2,6,4,5,3],outlen:[3,6,5],ssl:[2,6,4,5,3],cannot:[2,6,3],nghttpd:4,requir:[0,6,4,3],nghttp2_set_stream_user_data:2,nghttp2_frame_size_error:[3,6],detect:[3,6,4],"import":4,fcntl:2,pipefd:2,bump:[3,6],evdns_bas:5,typedef:[0,6,5,3,2],submit_request:5,region:[3,6],"0x000300":1,contract:[2,6,5,1],tutori:[0,5,2],deflatehd:4,mani:[3,6],nghttp2_data_provid:[2,6,3],unistd:[2,5],nghttp2_err_too_many_inflight_set:[3,6],cancel:[3,6],damag:[2,6,5,1],header_table_s:4,nghttp2_settings_max:[3,6],netdb:2,nghttp2_on_unknown_frame_recv_callback:[3,6],nghttp2_opt:[3,6],those:[2,6,5,3],"case":[2,6,4,5,3],hdr:[2,4,5],invok:[2,6,5,3],invoc:[2,6,3],on_data_chunk_recv_callback:[3,6,5],stdout:[4,5],ascii:[3,6],develop:[0,4],author:[2,6,4,5,1],bev_opt_defer_callback:[2,5],alphabet:[3,6],same:[2,6,4,5,3],ssl_library_init:[2,5],binari:5,pac:4,document:[0,1,2,4,5,6],finish:[2,5],decompress:[3,6,4],handshake_leftlen:2,extern:6,postpon:[3,6],macro:[0,6,1,3],without:[2,1,3,4,5,6],nghttp2_push_promis:[3,6],event2:[2,5],nghttp2_err_def:[3,6],nghttp2_submit_set:[2,6,5,3],execut:4,multiplex:[2,4],struct:[0,6,5,3,2],hint:2,except:[3,6],identif:[3,6],nghttp2_select_next_protocol:[3,6,5],real:5,read:[2,6,4,5,3],nghttp2_version_ag:[3,6],test:[0,4],next_proto_cb:2,integ:[3,6],server:[0,2,3,4,5,6],either:[2,6,3],output:[2,6,4,5,3],manag:[2,6,3],stream_clos:[3,6],ssl_ctx_set_next_protos_advertised_cb:2,handshak:[2,5],nonzero:[2,6,3],easili:5,exit:[2,5],refer:[0,6,4,3],base64url:[3,6],nghttp2_session_server_new:[2,6,3],fulli:2,getnameinfo:2,src:4,inflater_ptr:[3,6],ack:[3,6,4],dnsbase:5,settings_payload:[3,6],act:[2,5],routin:[2,5],no_auto_stream_window_upd:[3,6],least_vers:[3,6],error_repli:2,insuffici:[3,6],b2a_hex:4,nghttp2_hcat_respons:[3,6,5],hex:[2,4],start:[2,6,4,5,3],nghttp2_err_stream_clos:[3,6],low:[3,6],lot:[3,6],ipv6:4,strictli:[3,6],next_proto_list:2,nghttp2_proto_version_id_len:[2,6,3],nghttp2_err_invalid_st:[3,6],possibl:[2,6,5,3],"default":[2,6,4,3],applayerprotoneg:[3,6],hpack:[0,4],err_get_error:[2,5],expect:4,creat:[2,6,4,5,3],mainli:[3,6],decreas:[3,6],file:[2,1,3,4,5,6],nghttp2_err_invalid_header_block:[3,6],fill:2,denot:[3,6,5],functypedef:6,googl:4,field:[2,6,4,5,3],valid:[3,6,4],nghttp2_prioriti:[3,6],print_head:5,you:[2,6,4,5,3],sequenc:[2,6,4,5,3],reduc:[3,6],cunit:4,directori:[2,4,5],mask:[3,6],represent:[3,1],all:[2,6,5,1,3],on_unknown_frame_recv_callback:[3,6],illustr:4,nghttp2_err_start_stream_not_allow:[3,6],lack:[3,6],follow:[2,1,3,4,5,6],ptr:[2,6,5,3],app_cont:2,uint8_t:[2,6,5,3],readcb:[2,5],program:[0,4,5,2],bufferevent_writ:[2,5],uf_queri:5,far:[2,5],settings_header_table_s:[3,6,4],nghttp2_client_connection_header_len:[2,6,5,3],failur:[3,6],veri:[3,6,5],no_auto_connection_window_upd:[3,6],"__cplusplu":6,list:[2,6,3],nghttp2_headers_categori:[3,6],adjust:[3,6],stderr:[2,4,5],small:[3,6],session_recv:2,zero:[3,6],pass:[3,6,5],further:[2,6,5,3],what:[3,6,4],sub:2,sun:4,sum:4,delet:5,version:[0,6,4,1,3],method:[2,6,4,5,3],libjansson:4,percentage_of_original_s:4,excess:2,modifi:[2,6,4,5,1],valu:[2,6,4,5,3],search:2,ai_addrconfig:2,nghttp2_err_push_dis:[3,6],prior:4,amount:[2,5],action:[2,6,5,1,3],via:[2,6,4,5,3],primit:5,famili:[2,5],establish:[2,5],select:[3,6,4,5],regist:2,libev:[0,4,5,2],taken:[3,6],minor:[3,1],more:[2,6,4,5,3],tsujikawa:[2,6,5,1],nghttp2_settings_header_table_s:[3,6],nghttp2_pri_default:[3,6,5],flag:[2,6,4,5,3],sens:[3,6],known:[3,6],nghttp2_err_wouldblock:[2,6,5,3],endpoint:[3,6,4],dev:4,remain:[2,6,5,3],share:[3,6,4],accept:[2,6,4,3],minimum:2,ssl_op_al:[2,5],create_ssl:[2,5],strlen:[2,5],huge:[2,5],netinet:[2,5],secur:4,anoth:[3,6],serveraddr:4,reject:[3,6],sec9:[3,6],simpl:[2,6,5,3],resourc:[0,6,4,5,3],referenc:4,variant:[3,6],spdylai:4,associ:[2,1,3,4,5,6],"short":[2,5],caus:[3,6],callback:[2,6,5,3],alpn:[3,6,4],authroiti:5,hypertext:[0,4],libcunit1:4,through:[2,4],left:[3,6],paramet:[3,6,5],style:4,nghttp2_hcat_push_respons:[3,6],pend:[2,6,5,3],nghttp2_err_eof:[3,6],progoram:5,valuelen:[2,6,5,3],"0x010203":[3,1],"return":[2,6,4,5,3],check_path:2,synopsi:[2,5],nghttp2_initial_max_concurrent_stream:[3,6],readlen:2,nghttp2_err_callback_failur:[2,6,5,3],tear:[2,5],achiev:[2,6,3],found:[2,6,3],trailer:[3,6],nghttp2_on_frame_send_callback:[3,6],monoton:5,realli:5,connect:[2,1,3,4,5,6],field_set:5,event:[2,6,5,1],app_ctx:2,publish:[2,6,5,1],payload:[3,6],etag:4,print:[4,5],on_frame_not_send_callback:[3,6],proxi:[0,4],differ:[3,6],effect:[3,6],reason:[2,6,3],base:[2,4,5],put:[3,6],nghttp2_session_mem_recv:[2,6,5,3],nghttp2_flag:[3,6],recv:4,thread:[2,4],omit:[3,6,5],nghttp2_err_invalid_stream_st:[3,6],assign:[2,6,5,3],feed:[2,5],major:[3,1],notifi:2,prevent:[3,6],number:[2,6,1,3],"0x8":[3,6],done:[2,4,5],construct:[3,6],stdlib:6,nghttp2_internal_error:[2,6,3],script:4,data_prd:[2,6,3],nghttp2_session_get_stream_user_data:[2,6,5,3],least:[3,6,4],scheme:[4,5],store:[2,6,5,3],input_length:4,memset:[2,5],option:[2,6,4,5,3],similarli:[3,6],nghttp2_client_connection_head:[2,6,5,3],pars:5,kind:[2,6,5,1,3],doubli:2,remot:[2,6,4,5,3],remov:[2,6,3],bridg:4,ai_next:2,consumpt:[2,5],nghttp2_error:[3,6],window_size_incr:[3,6,4],lib_error_cod:[3,6],arrlen:[2,5],packag:4,"null":[2,6,5,3],syn_stream:[3,6],sell:[2,6,5,1],outbound:[3,6],equival:[3,6],afram:[3,6],also:[2,6,4,5,3],build:[0,4,5],nghttp2_err_frame_size_error:[3,6],make_nv:[2,5],distribut:[2,6,5,1],reacb:5,reach:[3,6],chart:[3,6],most:[3,6],vnu:4,charg:[2,6,5,1],addr:2,"01881f3468e5891afcbf83868a3d856659c62e3f":4,compar:[3,6,5],frame_size_error:[3,6,4],session:[2,6,5,3],nghttp2_submit_push_promis:[3,6],copyright:[2,6,5,1],refused_stream:[3,6],nghttp2_opt_no_auto_stream_window_upd:[3,6],queu:[2,6,5,3],express:[2,6,5,1],window_upd:[3,6,4],liabl:[2,6,5,1],before_frame_send_callback:[3,6,5],retreiv:5,crt:2,certif:[2,4,5],set:[2,6,4,5,3],seq:4,sep:4,ousid:4,remove_stream:2,nghttp2_submit_goawai:[3,6],arg:[2,6,5,3],close:[2,6,4,5,3],analog:[3,6],strchr:2,someth:[3,6],won:[2,6,3],hold:[3,6],nghttp2_on_data_chunk_recv_callback:[3,6,5],numer:[3,6,1],percent_decod:2,both:[2,6,4,5,3],last:[3,6,4],delimit:4,nghttp2_session_want_writ:[2,6,5,3],tempor:[3,6],context:[2,6,4,5,3],compression_error:[3,6],whole:[3,6],simpli:[2,5],point:[2,6,5,3],header:[0,2,3,4,5,6],shutdown:[2,6,5,3],suppli:[3,6],nghttp2_session:[2,6,5,3],backend:4,due:[3,6],empti:[2,6,4,5,3],send_respons:2,whom:[2,6,5,1],stdint:6,add_stream:2,flight:[3,6],nghttp2_err_nomem:[3,6],settings_enable_push:[3,6,4],nghttp2_session_terminate_sess:[3,6,5],buflen:[3,6],func:6,next_proto_list_len:2,look:[2,5],"while":[2,6,5,3],behavior:[3,6],error:[2,6,4,5,3],loop:[2,5],malloc:[2,5],nghttp2_session_callback:[2,6,5,3],readi:2,user_data:[2,6,5,3],itself:[2,6,5,3],flow_control_error:[3,6],grant:[2,6,5,1],belong:[3,6],create_http2_session_data:[2,5],decod:[2,6,3],uf_schema:5,mytyp:[3,6],inflat:[3,6,4],alert:4,moment:4,user:[3,6,4,5],implement:[0,2,3,4,5,6],nghttp2_h:6,noninfring:[2,6,5,1],entri:[3,6,4],nghttp:4,person:[2,6,5,1],uint32_t:[3,6],self:4,hd_side_request:4,end_push_promis:[3,6],nghttp2_gzip_infl:[3,6],on_frame_send_callback:[3,6],nghttp2_ping:[3,6],input:[2,6,4,5,3],subsequ:[3,6],bin:4,on_begin_headers_callback:[2,6,5,3],format:[2,6,4,5,3],http_parser:5,bit:[3,6,1],strstr:2,signal:[2,6,5,3],lib_error:[3,6],api:[0,6,3],some:[2,6,5,3],back:[3,6],sampl:4,sizeof:[2,5],libssl:4,lev_opt_reus:2,though:4,per:[3,6],larg:[3,6],make_nv2:5,machin:4,run:[2,6,4,5,3],step:[3,6],handshake_readcb:2,idl:[3,6],block:[2,6,4,5,3],nghttp2_err_paus:[3,6],nsm:6,within:4,nghttp2_send_callback:[3,6,5],nghttp2_opt_set:[3,6],occupi:4,inclus:[3,6],errno:2,bodi:[2,6,5,3],"long":[3,6],nghttp2:[0,1,2,3,4,5,6],includ:[0,1,2,3,4,5,6],forward:4,session_ptr:[3,6],link:[2,4],ni_maxhost:2,nghttp2_session_set_stream_user_data:[2,6,3],line:4,concaten:[3,6],utf:4,caller:[2,6,3],nghttpx:4,clear:[3,6],parser:5,repres:[3,6],"char":[2,6,5,3],incomplet:4,sublen:2,titl:2,invalid:[3,6],librari:[0,1,2,3,4,5,6],libtool:4,create_http2_stream_data:[2,5],algorithm:[3,6],nghttp2_submit_request:[3,6,5],namelen:[2,6,5,3],getaddrinfo:2,code:[2,6,4,5,3],queri:5,nghttp2_frame_hd:[3,6],cython:4,privat:2,send:[2,6,4,5,3],http_parser_url:5,lower:[3,6],aris:[2,6,5,1],fatal:[2,6,5,3],sent:[2,6,5,3],nghttp2_submit_p:[3,6],untouch:[3,6],relev:[2,5],tri:[3,6],magic:[2,5],http_parser_parse_url:5,"try":4,freed:4,pleas:[2,6,4,5,3],impli:[2,6,5,1],smaller:4,snprintf:5,"0x1":[3,6],"0x0":[3,6],"0x4":[3,6],download:[0,4],index:4,o_rdonli:2,settings_flow_control_opt:[3,6],access:4,experiment:[0,4],inspect:[3,6],ssl_ctx_set_opt:[2,5],nghttp2_enhance_your_calm:[3,6],len:[2,6,5,3],closur:[3,6,5],nghttp2_rst_stream:[3,6],ubuntu:4,becom:[2,6,1,3],sinc:[2,6,4,5,3],remark:[0,3],larger:[3,6],settings_payloadlen:[3,6],autoreconf:4,jansson:4,greac:[2,5],chang:[2,6,3],output_wouldblock_threshold:2,appli:[3,6],bufferev:[2,5],from:[0,1,2,3,4,5,6],commun:[2,4,5],binascii:4,upgrad:[3,6,4],next:[2,6,4,5,3],findproxyforurl:4,usr:4,nghttp2_nv:[2,6,5,3],jxck:4,goawai:[2,6,4,5,3],deflat:[3,6,4],account:[3,6,4,5],retriev:[2,6,5,3],tunnel:4,nghttp2_settings_id:[3,6],aliv:[2,6,3],sslv23_client_method:5,control:[3,6],process:[2,6,4,5,3],fprintf:[2,5],onlin:[3,4],serial:[2,6,5,3],evdns_base_fre:5,nghttp2_session_want_read:[2,6,5,3],ssl_ctx_use_privatekey_fil:2,evbas:[2,5],instead:[3,6],nullifi:[3,6],npn:[2,6,4,5,3],eventcb:[2,5],nghttp2_compression_error:[3,6],alloc:[2,6,3],bind:[0,4],nvlen:[2,6,5,3],correspond:[2,4],element:[2,6,3],issu:[0,6,3],stream_id:[2,6,4,5,3],nghttp2_connect_error:[3,6],ssize_t:[2,6,5,3],furnish:[2,6,5,1],move:[3,6],max_outlen:[3,6],therefor:[3,6,5],nghttp2_session_send:[2,6,5,3],inlen:[3,6,5],recept:[2,6,5,3],crash:3,greater:[3,6],handl:[2,5],nghttp2_goawai:[3,6],handi:5,automat:[3,6],anyth:5,uf_port:5,mode:4,ssl_filetype_pem:2,chunk:[3,6,5],nghttp2_err_temporal_callback_failur:[2,6,3],"static":[2,6,4,5,3],our:5,patch:[3,1],out:[2,1,3,4,5,6],variabl:4,req:[3,6],categori:[3,6,5],suitabl:[3,6],rel:2,field_data:5,recv_callback:[3,6],insid:4,releas:[0,1,3],could:[2,6,5,3],keep:[2,6,4,5,3],length:[2,6,4,5,3],outsid:[3,4],retain:[3,6],softwar:[2,6,5,1],addrinfo:2,date:4,prioriti:[3,6,5],unknown:[2,6,3],system:[2,5],messag:[3,6,5],attach:[2,5],termin:[2,6,4,5,3],ipv4:4,sa_handl:[2,5],enqueu:5,exactli:[2,4],nghttp2_err_header_comp:[3,6],see:[2,6,4,5,3],structur:[2,6,5,3],charact:[2,6,5,3],nghttp2_session_del:[2,6,5,3],bev:[2,5],ssl_new:[2,5],"function":[0,2,3,4,5,6],bufferevent_get_input:[2,5],corrupt:5,have:[2,6,4,5,3],reserv:[3,6],need:[3,6,4,5],ai_socktyp:2,"0x04":4,"0x05":4,"0x00":[3,6,4],nghttp2_err_flow_control:[3,6],nghttp2_refused_stream:[3,6],evbuffer_pullup:[2,5],which:[2,6,4,5,3],singl:[2,6,4,5,3],opaque_data_len:[3,6],unless:[3,6],bufferevent_openssl_socket_new:[2,5],settings_max_concurrent_stream:[2,6,4,5,3],stream_data:[2,5],deploi:4,"class":4,nghttp2_error_cod:[2,6,5,3],nghttp2_err_stream_id_not_avail:[3,6],url:[2,4],request:[2,6,4,5,3],uri:[4,5],pipe:2,determin:4,nghttp2_pack_settings_payload:[3,6],"0x0d":[3,6],"0x0a":[3,6],ssl_load_error_str:[2,5],text:4,bufferevent_get_output:[2,5],redirect:5,locat:5,should:[2,6,5,3],local:[3,6],meant:5,familiar:4,memcpi:[2,5],nghttp2_session_client_new2:[3,6],settings_initial_window_s:[3,6,4],nghttp2_data:[2,6,3],increas:[3,6,5],portion:[2,6,5,1,3],nghttp2_submit_respons:[2,6,3],enabl:[3,6,4],whether:[2,6,5,1],stuff:[3,6],contain:[2,6,4,5,3],nghttp2_window_upd:[3,6],frame:[2,6,4,5,3],knowledg:4,temporarili:[3,6],statu:[0,6,4,3,2],wire:[2,4,5],nghttp2_settings_entri:[2,6,5,3],written:[2,6,4,5,3],https_uri:5,nghttp2_initial_connection_window_s:[3,6],kei:[2,6,4,3],supporet:4,entir:[2,6,3],last_stream_id:[3,6,4],addit:[2,6,3],file_read_callback:2,nghttp2_proto_version_id:[2,6,5,3],equal:2,etc:[2,4,5],instanc:[3,6],uint16_t:[3,6,5],rfc2616:[3,6],commenc:5,respect:[3,6,5],nghttp2_recv_callback:[3,6],ssl_ctx_set_next_proto_select_cb:[3,6,5],adjsut:4,compon:5,json:4,treat:[2,6,3],immedi:[3,6],nghttp2_hcat_head:[3,6],sock_stream:2,evconnlisten:2,on_header_callback:[2,6,5,3],multi:4,defin:[2,6,5,1,3],eintr:2,helper:[3,6],on_request_recv:2,libxml2:4,squid:4,select_next_proto_cb:[3,6,5],archiv:[2,5],substanti:[2,6,5,1],incom:[2,6,4,3],let:[2,5],member:[2,6,3],python:[0,4],ifndef:[6,1],dyanmic:4,http:[0,1,2,3,4,5,6],hostnam:4,uf_host:5,dealloc:4,peer_max_concurrent_stream:[3,6],off:5,well:[2,5],app_context:2,inflatehd:4,exampl:[2,6,4,5,3],command:4,error_cod:[2,6,4,5,3],nghttp2_data_sourc:[2,6,3],usual:[3,6],paus:[3,6],less:[3,6],send_callback:[2,6,5,3],half:[3,6],obtain:[2,6,5,1],tcp:[2,5],web:[2,4],cert_fil:2,send_server_connection_head:2,priorit:[3,6],addrlen:2,add:[2,6,3],match:[2,5],gmt:4,know:[3,6],nva:[2,6,5,3],python3:4,resid:[2,5],like:[2,6,4,5,3],success:4,nghttp2_pri_lowest:[3,6],nghttp2_flag_end_head:[3,6],necessari:2,tlen:[3,6],page:[2,5],revers:4,nghttp2_session_client_new:[3,6,5],"export":2,nghttp2_session_get_effective_recv_data_length:[3,6],error_html:2,transport:5,lead:[3,6],avoid:[2,6,5,3],octet:[2,5],overlap:[3,6],isxdigit:2,outgo:[2,6,3],nghttp2_session_upgrad:[3,6],delete_http2_stream_data:[2,5],"enum":[0,6,3],usag:[2,6,4,5,3],host:[0,4,5,2],nghttp2_nv_compare_nam:[3,6],about:[2,6,5,3],actual:[2,6,5,3],socket:[2,4,5],nghttp2_gzip:[3,6],chrome:4,fals:4,ssl_tlsext_err_ok:[2,6,5,3],disabl:[3,6,4],own:[3,6],nghttp2_err_invalid_fram:[3,6],ssl_op_no_sslv2:[2,5],warranti:[2,6,5,1],automak:4,merg:[2,6,5,1],val:[2,5],ai_famili:2,transfer:[0,6,4,3],intention:[3,6],much:2,buz:4,unexpect:[3,6],bufferevent_fre:[2,5],overflow:[3,6],highest:[3,6],buf:[2,6,3],count:[3,6],succe:[3,6],nghttp2_stream_clos:[3,6],nghttp2_info:[3,6],googlecod:[3,6],displai:4,asynchron:[3,6],limit:[2,6,5,1],otherwis:[2,1,3,4,5,6],problem:[3,6],sockaddr:2,nghttp2_on_frame_not_send_callback:[3,6],strndup:5,"int":[2,6,5,3],nghttp2_flag_end_stream:[2,6,3],allow:[3,6,4],percent:2,detail:[3,6],other:[2,6,5,1,3],nghttp2_err_invalid_argu:[3,6],rememb:[2,5],outlen_ptr:[3,6],stat:2,err_error_str:[2,5],nghttp2_opt_peer_max_concurrent_stream:[3,6],rel_path:2,proto_str:[3,6],debian:4,session_data:[2,5],sphinx:4,eof:[2,6,3],reliabl:[3,6],indirectli:3,rule:[3,6],nghttp2_no_error:[3,6,5]},objtypes:{"0":"c:member","1":"c:macro","2":"c:type","3":"c:function"},titles:["nghttp2 - HTTP/2.0 C Library","nghttp2ver.h","Tutorial: HTTP/2.0 server","API Reference","nghttp2 - HTTP/2.0 C Library","Tutorial: HTTP/2.0 client","nghttp2.h"],objnames:{"0":["c","member","C member"],"1":["c","macro","C macro"],"2":["c","type","C type"],"3":["c","function","C function"]},filenames:["index","nghttp2ver.h","tutorial-server","apiref","package_README","tutorial-client","nghttp2.h"]}) \ No newline at end of file diff --git a/released-versions/v0.3.0/tutorial-client.html b/released-versions/v0.3.0/tutorial-client.html new file mode 100644 index 00000000..e7d19a33 --- /dev/null +++ b/released-versions/v0.3.0/tutorial-client.html @@ -0,0 +1,1237 @@ + + + + + + + + + + + Tutorial: HTTP/2.0 client — nghttp2 0.3.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+ +
+

Tutorial: HTTP/2.0 client¶

+

In this tutorial, we are going to write very primitive HTTP/2.0 +client. The complete source code, libevent-client.c, is attached at +the end of this page. It also resides in examples directory in the +archive or repository.

+

This simple client takes 1 argument, HTTPS URI, and retrieves the +resource denoted by the URI. Its synopsis is like this:

+
$ libevent-client HTTPS_URI
+
+

We use libevent in this tutorial to handle networking I/O. Please +note that nghttp2 itself does not depend on libevent.

+

First we do some setup routine for libevent and OpenSSL library in +function main() and run(), which is not so relevant to nghttp2 +library use. The one thing you should look at is setup NPN callback. +The NPN callback is used for the client to select the next application +protocol over the SSL/TLS transport. In this tutorial, we use +nghttp2_select_next_protocol() function to select the HTTP/2.0 +protocol the library supports:

+
static int select_next_proto_cb(SSL* ssl,
+                                unsigned char **out, unsigned char *outlen,
+                                const unsigned char *in, unsigned int inlen,
+                                void *arg)
+{
+  if(nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
+    errx(1, "Server did not advertise " NGHTTP2_PROTO_VERSION_ID);
+  }
+  return SSL_TLSEXT_ERR_OK;
+}
+
+
+

The callback is set to the SSL_CTX object using +SSL_CTX_set_next_proto_select_cb() function:

+
static SSL_CTX* create_ssl_ctx(void)
+{
+  SSL_CTX *ssl_ctx;
+  ssl_ctx = SSL_CTX_new(SSLv23_client_method());
+  if(!ssl_ctx) {
+    errx(1, "Could not create SSL/TLS context: %s",
+         ERR_error_string(ERR_get_error(), NULL));
+  }
+  SSL_CTX_set_options(ssl_ctx,
+                      SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION |
+                      SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
+  SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
+  return ssl_ctx;
+}
+
+
+

We use http2_session_data structure to store the data related to +the HTTP/2.0 session:

+
typedef struct {
+  nghttp2_session *session;
+  struct evdns_base *dnsbase;
+  struct bufferevent *bev;
+  http2_stream_data *stream_data;
+} http2_session_data;
+
+
+

Since this program only handles 1 URI, it uses only 1 stream. We store +its stream specific data in http2_stream_data structure and the +stream_data points to it. The struct http2_stream_data is +defined as follows:

+
typedef struct {
+  /* The NULL-terminated URI string to retreive. */
+  const char *uri;
+  /* Parsed result of the |uri| */
+  struct http_parser_url *u;
+  /* The authroity portion of the |uri|, not NULL-terminated */
+  char *authority;
+  /* The path portion of the |uri|, including query, not
+     NULL-terminated */
+  char *path;
+  /* The length of the |authority| */
+  size_t authoritylen;
+  /* The length of the |path| */
+  size_t pathlen;
+  /* The stream ID of this stream */
+  int32_t stream_id;
+} http2_stream_data;
+
+
+

We creates and initializes these structures in +create_http2_session_data() and create_http2_stream_data() +respectively.

+

Then we call function initiate_connection() to start connecting to +the remote server:

+
static void initiate_connection(struct event_base *evbase,
+                                SSL_CTX *ssl_ctx,
+                                const char *host, uint16_t port,
+                                http2_session_data *session_data)
+{
+  int rv;
+  struct bufferevent *bev;
+  SSL *ssl;
+
+  ssl = create_ssl(ssl_ctx);
+  bev = bufferevent_openssl_socket_new(evbase, -1, ssl,
+                                       BUFFEREVENT_SSL_CONNECTING,
+                                       BEV_OPT_DEFER_CALLBACKS |
+                                       BEV_OPT_CLOSE_ON_FREE);
+  bufferevent_setcb(bev, readcb, writecb, eventcb, session_data);
+  rv = bufferevent_socket_connect_hostname(bev, session_data->dnsbase,
+                                           AF_UNSPEC, host, port);
+
+  if(rv != 0) {
+    errx(1, "Could not connect to the remote host %s", host);
+  }
+  session_data->bev = bev;
+}
+
+
+

We set 3 callbacks for the bufferevent: reacb, writecb and +eventcb.

+

The eventcb() is invoked by libevent event loop when an event +(e.g., connection has been established, timeout, etc) happens on the +underlying network socket:

+
static void eventcb(struct bufferevent *bev, short events, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  if(events & BEV_EVENT_CONNECTED) {
+    int fd = bufferevent_getfd(bev);
+    int val = 1;
+    fprintf(stderr, "Connected\n");
+    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+    initialize_nghttp2_session(session_data);
+    send_client_connection_header(session_data);
+    submit_request(session_data);
+    if(session_send(session_data) != 0) {
+      delete_http2_session_data(session_data);
+    }
+    return;
+  }
+  if(events & BEV_EVENT_EOF) {
+    warnx("Disconnected from the remote host");
+  } else if(events & BEV_EVENT_ERROR) {
+    warnx("Network error");
+  } else if(events & BEV_EVENT_TIMEOUT) {
+    warnx("Timeout");
+  }
+  delete_http2_session_data(session_data);
+}
+
+
+

For BEV_EVENT_EOF, BEV_EVENT_ERROR and BEV_EVENT_TIMEOUT +event, we just simply tear down the connection. The +BEV_EVENT_CONNECTED event is invoked when SSL/TLS handshake is +finished successfully. We first initialize nghttp2 session object in +initialize_nghttp2_session() function:

+
static void initialize_nghttp2_session(http2_session_data *session_data)
+{
+  nghttp2_session_callbacks callbacks = {0};
+
+  callbacks.send_callback = send_callback;
+  callbacks.before_frame_send_callback = before_frame_send_callback;
+  callbacks.on_frame_recv_callback = on_frame_recv_callback;
+  callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
+  callbacks.on_stream_close_callback = on_stream_close_callback;
+  callbacks.on_header_callback = on_header_callback;
+  callbacks.on_begin_headers_callback = on_begin_headers_callback;
+  nghttp2_session_client_new(&session_data->session, &callbacks, session_data);
+}
+
+
+

Since we are creating client, we use nghttp2_session_client_new() to +initialize nghttp2 session object. We setup 7 callbacks for the +nghttp2 session. We’ll explain these callbacks later.

+

The delete_http2_session_data() destroys session_data and frees +its bufferevent, so it closes underlying connection as well. It also +calls nghttp2_session_del() to delete nghttp2 session object.

+

We begin HTTP/2.0 communication by sending client connection header, +which is 24 bytes magic byte sequence +(NGHTTP2_CLIENT_CONNECTION_HEADER) followed by SETTINGS +frame. The transmission of client connection header is done in +send_client_connection_header():

+
static void send_client_connection_header(http2_session_data *session_data)
+{
+  nghttp2_settings_entry iv[1] = {
+    { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }
+  };
+  int rv;
+
+  bufferevent_write(session_data->bev,
+                    NGHTTP2_CLIENT_CONNECTION_HEADER,
+                    NGHTTP2_CLIENT_CONNECTION_HEADER_LEN);
+  rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE,
+                               iv, ARRLEN(iv));
+  if(rv != 0) {
+    errx(1, "Could not submit SETTINGS: %s", nghttp2_strerror(rv));
+  }
+}
+
+
+

Here we specify SETTINGS_MAX_CONCURRENT_STREAMS to 100, which is +really not needed for this tiny example progoram, but we are +demonstrating the use of SETTINGS frame. To queue the SETTINGS frame +for the transmission, we use nghttp2_submit_settings(). Note that +nghttp2_submit_settings() function only queues the frame and not +actually send it. All nghttp2_submit_*() family functions have +this property. To actually send the frame, nghttp2_session_send() is +used, which is described about later.

+

After the transmission of client connection header, we enqueue HTTP +request in submit_request() function:

+
static void submit_request(http2_session_data *session_data)
+{
+  int rv;
+  http2_stream_data *stream_data = session_data->stream_data;
+  const char *uri = stream_data->uri;
+  const struct http_parser_url *u = stream_data->u;
+  nghttp2_nv hdrs[] = {
+    MAKE_NV2(":method", "GET"),
+    MAKE_NV(":scheme",
+            &uri[u->field_data[UF_SCHEMA].off], u->field_data[UF_SCHEMA].len),
+    MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
+    MAKE_NV(":path", stream_data->path, stream_data->pathlen)
+  };
+  fprintf(stderr, "Request headers:\n");
+  print_headers(stderr, hdrs, ARRLEN(hdrs));
+  rv = nghttp2_submit_request(session_data->session, NGHTTP2_PRI_DEFAULT,
+                              hdrs, ARRLEN(hdrs), NULL, stream_data);
+  if(rv != 0) {
+    errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(rv));
+  }
+}
+
+
+

We build HTTP request header fields in hdrs which is an array of +nghttp2_nv. There are 4 header fields to be sent: :method, +:scheme, :authority and :path. To queue this HTTP request, +we use nghttp2_submit_request() function. The stream_data() is +passed in stream_user_data parameter. It is used in nghttp2 +callbacks which we’ll describe about later.

+

The next bufferevent callback is readcb(), which is invoked when +data is available to read in the bufferevent input buffer:

+
static void readcb(struct bufferevent *bev, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  int rv;
+  struct evbuffer *input = bufferevent_get_input(bev);
+  size_t datalen = evbuffer_get_length(input);
+  unsigned char *data = evbuffer_pullup(input, -1);
+  rv = nghttp2_session_mem_recv(session_data->session, data, datalen);
+  if(rv < 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    delete_http2_session_data(session_data);
+    return;
+  }
+  evbuffer_drain(input, rv);
+  if(session_send(session_data) != 0) {
+    delete_http2_session_data(session_data);
+    return;
+  }
+}
+
+
+

In this function, we feed all unprocessed, received data to nghttp2 +session object using nghttp2_session_mem_recv() function. The +nghttp2_session_mem_recv() processes the received data and may +invoke nghttp2 callbacks and also queue frames. Since there may be +pending frames, we call session_send() function to send those +frames. The session_send() function is defined as follows:

+
static int session_send(http2_session_data *session_data)
+{
+  int rv;
+
+  rv = nghttp2_session_send(session_data->session);
+  if(rv != 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    return -1;
+  }
+  return 0;
+}
+
+
+

The nghttp2_session_send() function serializes the frame into wire +format and call nghttp2_session_callbacks.send_callback with +it. We set send_callback() function to +nghttp2_session_callbacks.send_callback in +initialize_nghttp2_session() function described earlier. It is +defined as follows:

+
static ssize_t send_callback(nghttp2_session *session,
+                             const uint8_t *data, size_t length,
+                             int flags, void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  struct bufferevent *bev = session_data->bev;
+  bufferevent_write(bev, data, length);
+  return length;
+}
+
+
+

Since we use bufferevent to abstract network I/O, we just write the +data to the bufferevent object. Note that nghttp2_session_send() +continues to write all frames queued so far. If we were writing the +data to the non-blocking socket directly using write() system call +in the nghttp2_session_callbacks.send_callback, we will +surely get EAGAIN or EWOULDBLOCK since the socket has limited +send buffer. If that happens, we can return +NGHTTP2_ERR_WOULDBLOCK to signal the nghttp2 library to stop +sending further data. But writing to the bufferevent, we have to +regulate the amount data to be buffered by ourselves to avoid possible +huge memory consumption. In this example client, we do not limit +anything. To see how to regulate the amount of buffered data, see the +send_callback() in the server tutorial.

+

The third bufferevent callback is writecb(), which is invoked when +all data written in the bufferevent output buffer have been sent:

+
static void writecb(struct bufferevent *bev, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  if(nghttp2_session_want_read(session_data->session) == 0 &&
+     nghttp2_session_want_write(session_data->session) == 0 &&
+     evbuffer_get_length(bufferevent_get_output(session_data->bev)) == 0) {
+    delete_http2_session_data(session_data);
+  }
+}
+
+
+

As described earlier, we just write off all data in send_callback(), +we have no data to write in this function. All we have to do is check +we have to drop connection or not. The nghttp2 session object keeps +track of reception and transmission of GOAWAY frame and other error +conditions as well. Using these information, nghttp2 session object +will tell whether the connection should be dropped or not. More +specifically, both nghttp2_session_want_read() and +nghttp2_session_want_write() return 0, we have no business in the +connection. But since we are using bufferevent and its deferred +callback option, the bufferevent output buffer may contain the pending +data when the writecb() is called. To handle this situation, we +also check whether the output buffer is empty or not. If these +conditions are met, we drop connection.

+

We have already described about nghttp2 callback send_callback(). +Let’s describe remaining nghttp2 callbacks we setup in +initialize_nghttp2_setup() function.

+

The before_frame_send_callback() function is invoked when a frame is +about to be sent:

+
static int before_frame_send_callback
+(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  http2_stream_data *stream_data;
+
+  if(frame->hd.type == NGHTTP2_HEADERS &&
+     frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
+    stream_data =
+      (http2_stream_data*)nghttp2_session_get_stream_user_data
+      (session, frame->hd.stream_id);
+    if(stream_data == session_data->stream_data) {
+      stream_data->stream_id = frame->hd.stream_id;
+    }
+  }
+  return 0;
+}
+
+
+

Remember that we have not get stream ID when we submit HTTP request +using nghttp2_submit_request(). Since nghttp2 library reorders the +request based on priority and stream ID must be monotonically +increased, the stream ID is not assigned just before transmission. +The one of the purpose of this callback is get the stream ID assigned +to the frame. First we check that the frame is HEADERS frame. Since +HEADERS has several meanings in HTTP/2.0, we check that it is request +HEADERS (which means that the first HEADERS frame to create a stream). +The assigned stream ID is frame->hd.stream_id. Recall that we +passed stream_data in the stream_user_data parameter of +nghttp2_submit_request() function. We can get it using +nghttp2_session_get_stream_user_data() function. To really sure that +this HEADERS frame is the request HEADERS we have queued, we check +that session_data->stream_data and stream_data returned from +nghttp2_session_get_stream_user_data() are pointing the same +location. In this example program, we just only uses 1 stream, it is +unnecessary to compare them, but real applications surely deal with +multiple streams, and stream_user_data is very handy to identify +which HEADERS we are seeing in the callback. Therefore we just show +how to use it here.

+

Each request header name/value pair is emitted via +on_header_callback function:

+
static int on_header_callback(nghttp2_session *session,
+                              const nghttp2_frame *frame,
+                              const uint8_t *name, size_t namelen,
+                              const uint8_t *value, size_t valuelen,
+                              void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  switch(frame->hd.type) {
+  case NGHTTP2_HEADERS:
+    if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
+       session_data->stream_data->stream_id == frame->hd.stream_id) {
+      /* Print response headers for the initiated request. */
+      print_header(stderr, name, namelen, value, valuelen);
+      break;
+    }
+  }
+  return 0;
+}
+
+
+

In this turotial, we just print the name/value pair.

+

After all name/value pairs are emitted for a frame, +on_frame_recv_callback function is called:

+
static int on_frame_recv_callback(nghttp2_session *session,
+                                  const nghttp2_frame *frame, void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  switch(frame->hd.type) {
+  case NGHTTP2_HEADERS:
+    if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
+       session_data->stream_data->stream_id == frame->hd.stream_id) {
+      fprintf(stderr, "All headers received\n");
+    }
+    break;
+  }
+  return 0;
+}
+
+
+

In this tutorial, we are just interested in the HTTP response +HEADERS. We check te frame type and its category (it should be +NGHTTP2_HCAT_RESPONSE for HTTP response HEADERS). Also check +its stream ID.

+

The on_data_chunk_recv_callback() function is invoked when a chunk +of data is received from the remote peer:

+
static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
+                                       int32_t stream_id,
+                                       const uint8_t *data, size_t len,
+                                       void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  if(session_data->stream_data->stream_id == stream_id) {
+    fwrite(data, len, 1, stdout);
+  }
+  return 0;
+}
+
+
+

In our case, a chunk of data is response body. After checking stream +ID, we just write the recieved data to the stdout. Note that the +output in the terminal may be corrupted if the response body contains +some binary data.

+

The on_stream_close_callback() function is invoked when the stream +is about to close:

+
static int on_stream_close_callback(nghttp2_session *session,
+                                    int32_t stream_id,
+                                    nghttp2_error_code error_code,
+                                    void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  int rv;
+
+  if(session_data->stream_data->stream_id == stream_id) {
+    fprintf(stderr, "Stream %d closed with error_code=%d\n",
+            stream_id, error_code);
+    rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
+    if(rv != 0) {
+      return NGHTTP2_ERR_CALLBACK_FAILURE;
+    }
+  }
+  return 0;
+}
+
+
+

If the stream ID matches the one we initiated, it means that its +stream is going to be closed. Since we have finished to get the +resource we want (or the stream was reset by RST_STREAM from the +remote peer), we call nghttp2_session_terminate_session() to +commencing the closure of the HTTP/2.0 session gracefully. If you have +some data associated for the stream to be closed, you may delete it +here.

+
+

libevent-client.c¶

+
/*
+ * nghttp2 - HTTP/2.0 C Library
+ *
+ * Copyright (c) 2013 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 <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <err.h>
+#include <signal.h>
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include <event.h>
+#include <event2/event.h>
+#include <event2/bufferevent_ssl.h>
+#include <event2/dns.h>
+
+#include <nghttp2/nghttp2.h>
+
+#include "http-parser/http_parser.h"
+
+#define ARRLEN(x) (sizeof(x)/sizeof(x[0]))
+
+typedef struct {
+  /* The NULL-terminated URI string to retreive. */
+  const char *uri;
+  /* Parsed result of the |uri| */
+  struct http_parser_url *u;
+  /* The authroity portion of the |uri|, not NULL-terminated */
+  char *authority;
+  /* The path portion of the |uri|, including query, not
+     NULL-terminated */
+  char *path;
+  /* The length of the |authority| */
+  size_t authoritylen;
+  /* The length of the |path| */
+  size_t pathlen;
+  /* The stream ID of this stream */
+  int32_t stream_id;
+} http2_stream_data;
+
+typedef struct {
+  nghttp2_session *session;
+  struct evdns_base *dnsbase;
+  struct bufferevent *bev;
+  http2_stream_data *stream_data;
+} http2_session_data;
+
+static http2_stream_data* create_http2_stream_data(const char *uri,
+                                                   struct http_parser_url *u)
+{
+  /* MAX 5 digits (max 65535) + 1 ':' + 1 NULL (because of snprintf) */
+  size_t extra = 7;
+  http2_stream_data *stream_data = malloc(sizeof(http2_stream_data));
+
+  stream_data->uri = uri;
+  stream_data->u = u;
+  stream_data->stream_id = -1;
+
+  stream_data->authoritylen = u->field_data[UF_HOST].len;
+  stream_data->authority = malloc(stream_data->authoritylen + extra);
+  memcpy(stream_data->authority,
+         &uri[u->field_data[UF_HOST].off], u->field_data[UF_HOST].len);
+  if(u->field_set & (1 << UF_PORT)) {
+    stream_data->authoritylen +=
+      snprintf(stream_data->authority + u->field_data[UF_HOST].len, extra,
+               ":%u", u->port);
+  }
+
+  stream_data->pathlen = 0;
+  if(u->field_set & (1 << UF_PATH)) {
+    stream_data->pathlen = u->field_data[UF_PATH].len;
+  }
+  if(u->field_set & (1 << UF_QUERY)) {
+    /* +1 for '?' character */
+    stream_data->pathlen += u->field_data[UF_QUERY].len + 1;
+  }
+  if(stream_data->pathlen > 0) {
+    stream_data->path = malloc(stream_data->pathlen);
+    if(u->field_set & (1 << UF_PATH)) {
+      memcpy(stream_data->path,
+             &uri[u->field_data[UF_PATH].off], u->field_data[UF_PATH].len);
+    }
+    if(u->field_set & (1 << UF_QUERY)) {
+      memcpy(stream_data->path + u->field_data[UF_PATH].len + 1,
+             &uri[u->field_data[UF_QUERY].off], u->field_data[UF_QUERY].len);
+    }
+  } else {
+    stream_data->path = NULL;
+  }
+  return stream_data;
+}
+
+static void delete_http2_stream_data(http2_stream_data *stream_data)
+{
+  free(stream_data->path);
+  free(stream_data->authority);
+  free(stream_data);
+}
+
+/* Initializes |session_data| */
+static http2_session_data *create_http2_session_data(struct event_base *evbase)
+{
+  http2_session_data *session_data = malloc(sizeof(http2_session_data));
+
+  memset(session_data, 0, sizeof(http2_session_data));
+  session_data->dnsbase = evdns_base_new(evbase, 1);
+  return session_data;
+}
+
+static void delete_http2_session_data(http2_session_data *session_data)
+{
+  SSL *ssl = bufferevent_openssl_get_ssl(session_data->bev);
+
+  if(ssl) {
+    SSL_shutdown(ssl);
+  }
+  bufferevent_free(session_data->bev);
+  session_data->bev = NULL;
+  evdns_base_free(session_data->dnsbase, 1);
+  session_data->dnsbase = NULL;
+  nghttp2_session_del(session_data->session);
+  session_data->session = NULL;
+  if(session_data->stream_data) {
+    delete_http2_stream_data(session_data->stream_data);
+    session_data->stream_data = NULL;
+  }
+  free(session_data);
+}
+
+static void print_header(FILE *f,
+                         const uint8_t *name, size_t namelen,
+                         const uint8_t *value, size_t valuelen)
+{
+  fwrite(name, namelen, 1, f);
+  fprintf(f, ": ");
+  fwrite(value, valuelen, 1, f);
+  fprintf(f, "\n");
+}
+
+/* Print HTTP headers to |f|. Please note that this function does not
+   take into account that header name and value are sequence of
+   octets, therefore they may contain non-printable characters. */
+static void print_headers(FILE *f, nghttp2_nv *nva, size_t nvlen)
+{
+  size_t i;
+  for(i = 0; i < nvlen; ++i) {
+    print_header(f,
+                 nva[i].name, nva[i].namelen,
+                 nva[i].value, nva[i].valuelen);
+  }
+  fprintf(f, "\n");
+}
+
+/* nghttp2_send_callback. Here we transmit the |data|, |length| bytes,
+   to the network. Because we are using libevent bufferevent, we just
+   write those bytes into bufferevent buffer. */
+static ssize_t send_callback(nghttp2_session *session,
+                             const uint8_t *data, size_t length,
+                             int flags, void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  struct bufferevent *bev = session_data->bev;
+  bufferevent_write(bev, data, length);
+  return length;
+}
+
+/* nghttp2_before_frame_send_callback: Called when nghttp2 library is
+   about to send a frame. We use this callback to get stream ID of new
+   stream. Since HEADERS in HTTP/2.0 has several roles, we check that
+   it is a HTTP request HEADERS. */
+static int before_frame_send_callback
+(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  http2_stream_data *stream_data;
+
+  if(frame->hd.type == NGHTTP2_HEADERS &&
+     frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
+    stream_data =
+      (http2_stream_data*)nghttp2_session_get_stream_user_data
+      (session, frame->hd.stream_id);
+    if(stream_data == session_data->stream_data) {
+      stream_data->stream_id = frame->hd.stream_id;
+    }
+  }
+  return 0;
+}
+
+/* nghttp2_on_header_callback: Called when nghttp2 library emits
+   single header name/value pair. */
+static int on_header_callback(nghttp2_session *session,
+                              const nghttp2_frame *frame,
+                              const uint8_t *name, size_t namelen,
+                              const uint8_t *value, size_t valuelen,
+                              void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  switch(frame->hd.type) {
+  case NGHTTP2_HEADERS:
+    if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
+       session_data->stream_data->stream_id == frame->hd.stream_id) {
+      /* Print response headers for the initiated request. */
+      print_header(stderr, name, namelen, value, valuelen);
+      break;
+    }
+  }
+  return 0;
+}
+
+/* nghttp2_on_begin_headers_callback: Called when nghttp2 library gets
+   started to receive header block. */
+static int on_begin_headers_callback(nghttp2_session *session,
+                                     const nghttp2_frame *frame,
+                                     void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  switch(frame->hd.type) {
+  case NGHTTP2_HEADERS:
+    if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
+       session_data->stream_data->stream_id == frame->hd.stream_id) {
+      fprintf(stderr, "Response headers for stream ID=%d:\n",
+              frame->hd.stream_id);
+    }
+    break;
+  }
+  return 0;
+}
+
+/* nghttp2_on_frame_recv_callback: Called when nghttp2 library
+   received a complete frame from the remote peer. */
+static int on_frame_recv_callback(nghttp2_session *session,
+                                  const nghttp2_frame *frame, void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  switch(frame->hd.type) {
+  case NGHTTP2_HEADERS:
+    if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
+       session_data->stream_data->stream_id == frame->hd.stream_id) {
+      fprintf(stderr, "All headers received\n");
+    }
+    break;
+  }
+  return 0;
+}
+
+/* nghttp2_on_data_chunk_recv_callback: Called when DATA frame is
+   received from the remote peer. In this implementation, if the frame
+   is meant to the stream we initiated, print the received data in
+   stdout, so that the user can redirect its output to the file
+   easily. */
+static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
+                                       int32_t stream_id,
+                                       const uint8_t *data, size_t len,
+                                       void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  if(session_data->stream_data->stream_id == stream_id) {
+    fwrite(data, len, 1, stdout);
+  }
+  return 0;
+}
+
+/* nghttp2_on_stream_close_callback: Called when a stream is about to
+   closed. This example program only deals with 1 HTTP request (1
+   stream), if it is closed, we send GOAWAY and tear down the
+   session */
+static int on_stream_close_callback(nghttp2_session *session,
+                                    int32_t stream_id,
+                                    nghttp2_error_code error_code,
+                                    void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  int rv;
+
+  if(session_data->stream_data->stream_id == stream_id) {
+    fprintf(stderr, "Stream %d closed with error_code=%d\n",
+            stream_id, error_code);
+    rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
+    if(rv != 0) {
+      return NGHTTP2_ERR_CALLBACK_FAILURE;
+    }
+  }
+  return 0;
+}
+
+/* NPN TLS extension client callback. We check that server advertised
+   the HTTP/2.0 protocol the nghttp2 library supports. If not, exit
+   the program. */
+static int select_next_proto_cb(SSL* ssl,
+                                unsigned char **out, unsigned char *outlen,
+                                const unsigned char *in, unsigned int inlen,
+                                void *arg)
+{
+  if(nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
+    errx(1, "Server did not advertise " NGHTTP2_PROTO_VERSION_ID);
+  }
+  return SSL_TLSEXT_ERR_OK;
+}
+
+/* Create SSL_CTX. */
+static SSL_CTX* create_ssl_ctx(void)
+{
+  SSL_CTX *ssl_ctx;
+  ssl_ctx = SSL_CTX_new(SSLv23_client_method());
+  if(!ssl_ctx) {
+    errx(1, "Could not create SSL/TLS context: %s",
+         ERR_error_string(ERR_get_error(), NULL));
+  }
+  SSL_CTX_set_options(ssl_ctx,
+                      SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION |
+                      SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
+  SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
+  return ssl_ctx;
+}
+
+/* Create SSL object */
+static SSL* create_ssl(SSL_CTX *ssl_ctx)
+{
+  SSL *ssl;
+  ssl = SSL_new(ssl_ctx);
+  if(!ssl) {
+    errx(1, "Could not create SSL/TLS session object: %s",
+         ERR_error_string(ERR_get_error(), NULL));
+  }
+  return ssl;
+}
+
+static void initialize_nghttp2_session(http2_session_data *session_data)
+{
+  nghttp2_session_callbacks callbacks = {0};
+
+  callbacks.send_callback = send_callback;
+  callbacks.before_frame_send_callback = before_frame_send_callback;
+  callbacks.on_frame_recv_callback = on_frame_recv_callback;
+  callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
+  callbacks.on_stream_close_callback = on_stream_close_callback;
+  callbacks.on_header_callback = on_header_callback;
+  callbacks.on_begin_headers_callback = on_begin_headers_callback;
+  nghttp2_session_client_new(&session_data->session, &callbacks, session_data);
+}
+
+static void send_client_connection_header(http2_session_data *session_data)
+{
+  nghttp2_settings_entry iv[1] = {
+    { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }
+  };
+  int rv;
+
+  bufferevent_write(session_data->bev,
+                    NGHTTP2_CLIENT_CONNECTION_HEADER,
+                    NGHTTP2_CLIENT_CONNECTION_HEADER_LEN);
+  rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE,
+                               iv, ARRLEN(iv));
+  if(rv != 0) {
+    errx(1, "Could not submit SETTINGS: %s", nghttp2_strerror(rv));
+  }
+}
+
+#define MAKE_NV(NAME, VALUE, VALUELEN)                                  \
+  { (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, VALUELEN }
+
+#define MAKE_NV2(NAME, VALUE)                                           \
+  { (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1 }
+
+/* Send HTTP request to the remote peer */
+static void submit_request(http2_session_data *session_data)
+{
+  int rv;
+  http2_stream_data *stream_data = session_data->stream_data;
+  const char *uri = stream_data->uri;
+  const struct http_parser_url *u = stream_data->u;
+  nghttp2_nv hdrs[] = {
+    MAKE_NV2(":method", "GET"),
+    MAKE_NV(":scheme",
+            &uri[u->field_data[UF_SCHEMA].off], u->field_data[UF_SCHEMA].len),
+    MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
+    MAKE_NV(":path", stream_data->path, stream_data->pathlen)
+  };
+  fprintf(stderr, "Request headers:\n");
+  print_headers(stderr, hdrs, ARRLEN(hdrs));
+  rv = nghttp2_submit_request(session_data->session, NGHTTP2_PRI_DEFAULT,
+                              hdrs, ARRLEN(hdrs), NULL, stream_data);
+  if(rv != 0) {
+    errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(rv));
+  }
+}
+
+/* Serialize the frame and send (or buffer) the data to
+   bufferevent. */
+static int session_send(http2_session_data *session_data)
+{
+  int rv;
+
+  rv = nghttp2_session_send(session_data->session);
+  if(rv != 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    return -1;
+  }
+  return 0;
+}
+
+/* readcb for bufferevent. Here we get the data from the input buffer
+   of bufferevent and feed them to nghttp2 library. This may invoke
+   nghttp2 callbacks. It may also queues the frame in nghttp2 session
+   context. To send them, we call session_send() in the end. */
+static void readcb(struct bufferevent *bev, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  int rv;
+  struct evbuffer *input = bufferevent_get_input(bev);
+  size_t datalen = evbuffer_get_length(input);
+  unsigned char *data = evbuffer_pullup(input, -1);
+  rv = nghttp2_session_mem_recv(session_data->session, data, datalen);
+  if(rv < 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    delete_http2_session_data(session_data);
+    return;
+  }
+  evbuffer_drain(input, rv);
+  if(session_send(session_data) != 0) {
+    delete_http2_session_data(session_data);
+    return;
+  }
+}
+
+/* writecb for bufferevent. To greaceful shutdown after sending or
+   receiving GOAWAY, we check the some conditions on the nghttp2
+   library and output buffer of bufferevent. If it indicates we have
+   no business to this session, tear down the connection. */
+static void writecb(struct bufferevent *bev, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  if(nghttp2_session_want_read(session_data->session) == 0 &&
+     nghttp2_session_want_write(session_data->session) == 0 &&
+     evbuffer_get_length(bufferevent_get_output(session_data->bev)) == 0) {
+    delete_http2_session_data(session_data);
+  }
+}
+
+/* eventcb for bufferevent. For the purpose of simplicity and
+   readability of the example program, we omitted the certificate and
+   peer verification. After SSL/TLS handshake is over, initialize
+   nghttp2 library session, and send client connection header. Then
+   send HTTP request. */
+static void eventcb(struct bufferevent *bev, short events, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  if(events & BEV_EVENT_CONNECTED) {
+    int fd = bufferevent_getfd(bev);
+    int val = 1;
+    fprintf(stderr, "Connected\n");
+    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+    initialize_nghttp2_session(session_data);
+    send_client_connection_header(session_data);
+    submit_request(session_data);
+    if(session_send(session_data) != 0) {
+      delete_http2_session_data(session_data);
+    }
+    return;
+  }
+  if(events & BEV_EVENT_EOF) {
+    warnx("Disconnected from the remote host");
+  } else if(events & BEV_EVENT_ERROR) {
+    warnx("Network error");
+  } else if(events & BEV_EVENT_TIMEOUT) {
+    warnx("Timeout");
+  }
+  delete_http2_session_data(session_data);
+}
+
+/* Start connecting to the remote peer |host:port| */
+static void initiate_connection(struct event_base *evbase,
+                                SSL_CTX *ssl_ctx,
+                                const char *host, uint16_t port,
+                                http2_session_data *session_data)
+{
+  int rv;
+  struct bufferevent *bev;
+  SSL *ssl;
+
+  ssl = create_ssl(ssl_ctx);
+  bev = bufferevent_openssl_socket_new(evbase, -1, ssl,
+                                       BUFFEREVENT_SSL_CONNECTING,
+                                       BEV_OPT_DEFER_CALLBACKS |
+                                       BEV_OPT_CLOSE_ON_FREE);
+  bufferevent_setcb(bev, readcb, writecb, eventcb, session_data);
+  rv = bufferevent_socket_connect_hostname(bev, session_data->dnsbase,
+                                           AF_UNSPEC, host, port);
+
+  if(rv != 0) {
+    errx(1, "Could not connect to the remote host %s", host);
+  }
+  session_data->bev = bev;
+}
+
+/* Get resource denoted by the |uri|. The debug and error messages are
+   printed in stderr, while the response body is printed in stdout. */
+static void run(const char *uri)
+{
+  struct http_parser_url u;
+  char *host;
+  uint16_t port;
+  int rv;
+  SSL_CTX *ssl_ctx;
+  struct event_base *evbase;
+  http2_session_data *session_data;
+
+  /* Parse the |uri| and stores its components in |u| */
+  rv = http_parser_parse_url(uri, strlen(uri), 0, &u);
+  if(rv != 0) {
+    errx(1, "Could not parse URI %s", uri);
+  }
+  host = strndup(&uri[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len);
+  if(!(u.field_set & (1 << UF_PORT))) {
+    port = 443;
+  } else {
+    port = u.port;
+  }
+
+  ssl_ctx = create_ssl_ctx();
+
+  evbase = event_base_new();
+
+  session_data = create_http2_session_data(evbase);
+  session_data->stream_data = create_http2_stream_data(uri, &u);
+
+  initiate_connection(evbase, ssl_ctx, host, port, session_data);
+  free(host);
+  host = NULL;
+
+  event_base_loop(evbase, 0);
+
+  event_base_free(evbase);
+  SSL_CTX_free(ssl_ctx);
+}
+
+int main(int argc, char **argv)
+{
+  struct sigaction act;
+
+  if(argc < 2) {
+    fprintf(stderr, "Usage: libevent-client HTTPS_URI\n");
+    exit(EXIT_FAILURE);
+  }
+
+  memset(&act, 0, sizeof(struct sigaction));
+  act.sa_handler = SIG_IGN;
+  sigaction(SIGPIPE, &act, NULL);
+
+  SSL_load_error_strings();
+  SSL_library_init();
+
+  run(argv[1]);
+  return 0;
+}
+
+
+
+
+ + +
+ +
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/released-versions/v0.3.0/tutorial-server.html b/released-versions/v0.3.0/tutorial-server.html new file mode 100644 index 00000000..ba790981 --- /dev/null +++ b/released-versions/v0.3.0/tutorial-server.html @@ -0,0 +1,1500 @@ + + + + + + + + + + + Tutorial: HTTP/2.0 server — nghttp2 0.3.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+ +
+

Tutorial: HTTP/2.0 server¶

+

In this tutorial, we are going to write single-threaded, event-based +HTTP/2.0 web server, which supports HTTPS only. It can handle +concurrent multiple requests, but only GET method is supported. The +complete source code, libevent-server.c, is attached at the end of +this page. It also resides in examples directory in the archive or +repository.

+

This simple server takes 3 arguments, a port number to listen to, a +path to SSL/TLS private key file and certificate file. Its synopsis +is like this:

+
$ libevent-server PORT /path/to/server.key /path/to/server.crt
+
+

We use libevent in this tutorial to handle networking I/O. Please +note that nghttp2 itself does not depend on libevent.

+

First we do some setup routine for libevent and OpenSSL library in +function main() and run(), which is not so relevant to nghttp2 +library use. The one thing you should look at is setup NPN callback. +The NPN callback is used for the server to advertise the application +protocols the server supports to a client. In this example program, +when creating SSL_CTX object, we stores the application protocol +name in the wire format of NPN in statically allocated buffer. This is +safe because we only create 1 SSL_CTX object in the entire program +life time:

+
static unsigned char next_proto_list[256];
+static size_t next_proto_list_len;
+
+static int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
+                         void *arg)
+{
+  *data = next_proto_list;
+  *len = next_proto_list_len;
+  return SSL_TLSEXT_ERR_OK;
+}
+
+
+static SSL_CTX* create_ssl_ctx(const char *key_file, const char *cert_file)
+{
+  SSL_CTX *ssl_ctx;
+  ssl_ctx = SSL_CTX_new(SSLv23_server_method());
+
+  ...
+
+  next_proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
+  memcpy(&next_proto_list[1], NGHTTP2_PROTO_VERSION_ID,
+         NGHTTP2_PROTO_VERSION_ID_LEN);
+  next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
+
+  SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
+  return ssl_ctx;
+}
+
+
+

The wire format of NPN is a sequence of length prefixed string. The +exactly one byte is used to specify the length of each protocol +identifier. In this tutorial, we advertise the HTTP/2.0 protocol the +nghttp2 library supports. The nghttp2 library exports its identifier +in NGHTTP2_PROTO_VERSION_ID. The next_proto_cb() function +is the server-side NPN callback. In OpenSSL implementation, we just +assign the pointer to the NPN buffers we filled earlier. The NPN +callback function is set to SSL_CTX object using +SSL_CTX_set_next_protos_advertised_cb().

+

We use app_content structure to store the application-wide data:

+
struct app_context {
+  SSL_CTX *ssl_ctx;
+  struct event_base *evbase;
+};
+
+
+

We use http2_session_data structure to store the session-level +(which corresponds to 1 HTTP/2.0 connection) data:

+
typedef struct http2_session_data {
+  struct http2_stream_data root;
+  struct bufferevent *bev;
+  app_context *app_ctx;
+  nghttp2_session *session;
+  char *client_addr;
+  size_t handshake_leftlen;
+} http2_session_data;
+
+
+

We use http2_stream_data structure to store the stream-level +data:

+
typedef struct http2_stream_data {
+  struct http2_stream_data *prev, *next;
+  char *request_path;
+  int32_t stream_id;
+  int fd;
+} http2_stream_data;
+
+
+

1 HTTP/2.0 session can have multiple streams. We manage these +multiple streams by intrusive doubly linked list to add and remove the +object in O(1). The first element of this list is pointed by the +root->next in http2_session_data. Initially, root->next +is NULL. The handshake_leftlen member of +http2_session_data is used to track the number of bytes remaining +when receiving first 24 bytes magic value +(NGHTTP2_CLIENT_CONNECTION_HEADER) from the client. We use +libevent’s bufferevent structure to perform network I/O. Notice that +bufferevent object is in http2_session_data and not in +http2_stream_data. This is because http2_stream_data is just a +logical stream multiplexed over the single connection managed by +bufferevent in http2_session_data.

+

We first create listener object to accept incoming connections. +We use libevent’s struct evconnlistener for this purpose:

+
static void start_listen(struct event_base *evbase, const char *service,
+                         app_context *app_ctx)
+{
+  int rv;
+  struct addrinfo hints;
+  struct addrinfo *res, *rp;
+
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_flags = AI_PASSIVE;
+#ifdef AI_ADDRCONFIG
+  hints.ai_flags |= AI_ADDRCONFIG;
+#endif // AI_ADDRCONFIG
+
+  rv = getaddrinfo(NULL, service, &hints, &res);
+  if(rv != 0) {
+    errx(1, NULL);
+  }
+  for(rp = res; rp; rp = rp->ai_next) {
+    struct evconnlistener *listener;
+    listener = evconnlistener_new_bind(evbase, acceptcb, app_ctx,
+                                       LEV_OPT_CLOSE_ON_FREE |
+                                       LEV_OPT_REUSEABLE, -1,
+                                       rp->ai_addr, rp->ai_addrlen);
+    if(listener) {
+      return;
+    }
+  }
+  errx(1, "Could not start listener");
+}
+
+
+

We specify acceptcb callback which is called when a new connection +is accepted:

+
static void acceptcb(struct evconnlistener *listener, int fd,
+                     struct sockaddr *addr, int addrlen, void *arg)
+{
+  app_context *app_ctx = (app_context*)arg;
+  http2_session_data *session_data;
+
+  session_data = create_http2_session_data(app_ctx, fd, addr, addrlen);
+  bufferevent_setcb(session_data->bev, handshake_readcb, NULL, eventcb,
+                    session_data);
+}
+
+
+

Here we create http2_session_data object. The bufferevent for this +connection is also initialized at this time. We specify 2 callbacks +for the bufferevent: handshake_readcb and eventcb.

+

The eventcb() is invoked by libevent event loop when an event +(e.g., connection has been established, timeout, etc) happens on the +underlying network socket:

+
static void eventcb(struct bufferevent *bev, short events, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  if(events & BEV_EVENT_CONNECTED) {
+    fprintf(stderr, "%s connected\n", session_data->client_addr);
+    return;
+  }
+  if(events & BEV_EVENT_EOF) {
+    fprintf(stderr, "%s EOF\n", session_data->client_addr);
+  } else if(events & BEV_EVENT_ERROR) {
+    fprintf(stderr, "%s network error\n", session_data->client_addr);
+  } else if(events & BEV_EVENT_TIMEOUT) {
+    fprintf(stderr, "%s timeout\n", session_data->client_addr);
+  }
+  delete_http2_session_data(session_data);
+}
+
+
+

For BEV_EVENT_EOF, BEV_EVENT_ERROR and BEV_EVENT_TIMEOUT +event, we just simply tear down the connection. The +delete_http2_session_data() function destroys +http2_session_data object and thus its bufferevent member. As a +result, the underlying connection is closed. The +BEV_EVENT_CONNECTED event is invoked when SSL/TLS handshake is +finished successfully.

+

The handshake_readcb() is a callback function to handle 24 bytes +magic byte string from a client, since nghttp2 library does not handle +it:

+
static void handshake_readcb(struct bufferevent *bev, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  uint8_t data[24];
+  struct evbuffer *input = bufferevent_get_input(session_data->bev);
+  int readlen = evbuffer_remove(input, data, session_data->handshake_leftlen);
+  const char *conhead = NGHTTP2_CLIENT_CONNECTION_HEADER;
+
+  if(memcmp(conhead + NGHTTP2_CLIENT_CONNECTION_HEADER_LEN
+            - session_data->handshake_leftlen, data, readlen) != 0) {
+    delete_http2_session_data(session_data);
+    return;
+  }
+  session_data->handshake_leftlen -= readlen;
+  if(session_data->handshake_leftlen == 0) {
+    bufferevent_setcb(session_data->bev, readcb, writecb, eventcb, ptr);
+    /* Process pending data in buffer since they are not notified
+       further */
+    initialize_nghttp2_session(session_data);
+    if(send_server_connection_header(session_data) != 0) {
+      delete_http2_session_data(session_data);
+      return;
+    }
+    if(session_recv(session_data) != 0) {
+      delete_http2_session_data(session_data);
+      return;
+    }
+  }
+}
+
+
+

We check that the received byte string matches +NGHTTP2_CLIENT_CONNECTION_HEADER. When they match, the +connection state is ready for starting HTTP/2.0 communication. First +we change the callback functions for the bufferevent object. We use +same eventcb as before. But we specify new readcb and +writecb function to handle HTTP/2.0 communication. We describe +these 2 functions later.

+

We initialize nghttp2 session object which is done in +initialize_nghttp2_session():

+
static void initialize_nghttp2_session(http2_session_data *session_data)
+{
+  nghttp2_session_callbacks callbacks = {0};
+
+  callbacks.send_callback = send_callback;
+  callbacks.on_frame_recv_callback = on_frame_recv_callback;
+  callbacks.on_stream_close_callback = on_stream_close_callback;
+  callbacks.on_header_callback = on_header_callback;
+  callbacks.on_begin_headers_callback = on_begin_headers_callback;
+  nghttp2_session_server_new(&session_data->session, &callbacks, session_data);
+}
+
+
+

Since we are creating server, nghttp2 session object is created using +nghttp2_session_server_new() function. We registers 5 callbacks to +nghttp2 session object. We’ll talk about these callbacks later.

+

After initialization of nghttp2 session object, we are going to send +server connection header in send_server_connection_header():

+
static int send_server_connection_header(http2_session_data *session_data)
+{
+  nghttp2_settings_entry iv[1] = {
+    { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }
+  };
+  int rv;
+
+  rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE,
+                               iv, ARRLEN(iv));
+  if(rv != 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    return -1;
+  }
+  return 0;
+}
+
+
+

The server connection header is SETTINGS frame. We specify +SETTINGS_MAX_CONCURRENT_STREAMS to 100 in SETTINGS frame. To queue +the SETTINGS frame for the transmission, we use +nghttp2_submit_settings(). Note that nghttp2_submit_settings() +function only queues the frame and not actually send it. All +nghttp2_submit_*() family functions have this property. To +actually send the frame, nghttp2_session_send() is used, which is +described about later.

+

Since bufferevent may buffer more than first 24 bytes from the client, +we have to process them here since libevent won’t invoke callback +functions for these pending data. To process received data, we call +session_recv() function:

+
static int session_recv(http2_session_data *session_data)
+{
+  int rv;
+  struct evbuffer *input = bufferevent_get_input(session_data->bev);
+  size_t datalen = evbuffer_get_length(input);
+  unsigned char *data = evbuffer_pullup(input, -1);
+  rv = nghttp2_session_mem_recv(session_data->session, data, datalen);
+  if(rv < 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    return -1;
+  }
+  evbuffer_drain(input, rv);
+  if(session_send(session_data) != 0) {
+    return -1;
+  }
+  return 0;
+}
+
+
+

In this function, we feed all unprocessed, received data to nghttp2 +session object using nghttp2_session_mem_recv() function. The +nghttp2_session_mem_recv() processes the received data and may +invoke nghttp2 callbacks and also queue outgoing frames. Since there +may be pending frames, we call session_send() function to send +those frames. The session_send() function is defined as follows:

+
static int session_send(http2_session_data *session_data)
+{
+  int rv;
+  rv = nghttp2_session_send(session_data->session);
+  if(rv != 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    return -1;
+  }
+  return 0;
+}
+
+
+

The nghttp2_session_send() function serializes the frame into wire +format and call nghttp2_session_callbacks.send_callback with +it. We set send_callback() function to +nghttp2_session_callbacks.send_callback in +initialize_nghttp2_session() function described earlier. It is +defined as follows:

+
static ssize_t send_callback(nghttp2_session *session,
+                             const uint8_t *data, size_t length,
+                             int flags, void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  struct bufferevent *bev = session_data->bev;
+  /* Avoid excessive buffering in server side. */
+  if(evbuffer_get_length(bufferevent_get_output(session_data->bev)) >=
+     OUTPUT_WOULDBLOCK_THRESHOLD) {
+    return NGHTTP2_ERR_WOULDBLOCK;
+  }
+  bufferevent_write(bev, data, length);
+  return length;
+}
+
+
+

Since we use bufferevent to abstract network I/O, we just write the +data to the bufferevent object. Note that nghttp2_session_send() +continues to write all frames queued so far. If we were writing the +data to the non-blocking socket directly using write() system call +in the nghttp2_session_callbacks.send_callback, we will +surely get EAGAIN or EWOULDBLOCK since the socket has limited +send buffer. If that happens, we can return +NGHTTP2_ERR_WOULDBLOCK to signal the nghttp2 library to stop +sending further data. But writing to the bufferevent, we have to +regulate the amount data to be buffered by ourselves to avoid possible +huge memory consumption. To achieve this, we check the size of output +buffer and if it is more than or equal to +OUTPUT_WOULDBLOCK_THRESHOLD bytes, we stop writing data and return +NGHTTP2_ERR_WOULDBLOCK to tell the library to stop calling +send_callback.

+

The next bufferevent callback is readcb(), which is invoked when +data is available to read in the bufferevent input buffer:

+
static void readcb(struct bufferevent *bev, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  if(session_recv(session_data) != 0) {
+    delete_http2_session_data(session_data);
+    return;
+  }
+}
+
+
+

In this function, we just call session_recv() to process incoming +data.

+

The third bufferevent callback is writecb(), which is invoked when +all data written in the bufferevent output buffer have been sent:

+
static void writecb(struct bufferevent *bev, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  if(evbuffer_get_length(bufferevent_get_output(bev)) > 0) {
+    return;
+  }
+  if(nghttp2_session_want_read(session_data->session) == 0 &&
+     nghttp2_session_want_write(session_data->session) == 0) {
+    delete_http2_session_data(session_data);
+    return;
+  }
+  if(session_send(session_data) != 0) {
+    delete_http2_session_data(session_data);
+    return;
+  }
+}
+
+
+

First we check whether we should drop connection or not. The nghttp2 +session object keeps track of reception and transmission of GOAWAY +frame and other error conditions as well. Using these information, +nghttp2 session object will tell whether the connection should be +dropped or not. More specifically, both nghttp2_session_want_read() +and nghttp2_session_want_write() return 0, we have no business in +the connection. But since we are using bufferevent and its deferred +callback option, the bufferevent output buffer may contain the pending +data when the writecb() is called. To handle this situation, we +also check whether the output buffer is empty or not. If these +conditions are met, we drop connection.

+

Otherwise, we call session_send() to process pending output +data. Remember that in send_callback(), we may not write all data +to bufferevent to avoid excessive buffering. We continue process +pending data when output buffer becomes empty.

+

We have already described about nghttp2 callback send_callback(). +Let’s describe remaining nghttp2 callbacks we setup in +initialize_nghttp2_setup() function.

+

The on_begin_headers_callback() function is invoked when reception +of header block in HEADERS or PUSH_PROMISE frame is started:

+
static int on_begin_headers_callback(nghttp2_session *session,
+                                     const nghttp2_frame *frame,
+                                     void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  http2_stream_data *stream_data;
+
+  if(frame->hd.type != NGHTTP2_HEADERS ||
+     frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
+    return 0;
+  }
+  stream_data = create_http2_stream_data(session_data, frame->hd.stream_id);
+  nghttp2_session_set_stream_user_data(session, frame->hd.stream_id,
+                                       stream_data);
+  return 0;
+}
+
+
+

We only interested in HEADERS frame in this function. Since HEADERS +frame has several roles in HTTP/2.0 protocol, we check that it is a +request HEADERS, which opens new stream. If frame is request HEADERS, +then we create http2_stream_data object to store stream related +data. We associate created http2_stream_data object to the stream +in nghttp2 session object using nghttp2_set_stream_user_data() in +order to get the object without searching through doubly linked list.

+

In this example server, we want to serve files relative to the current +working directory the program was invoked. Each header name/value pair +is emitted via on_header_callback function, which is called after +on_begin_headers_callback():

+
static int on_header_callback(nghttp2_session *session,
+                              const nghttp2_frame *frame,
+                              const uint8_t *name, size_t namelen,
+                              const uint8_t *value, size_t valuelen,
+                              void *user_data)
+{
+  http2_stream_data *stream_data;
+  const char PATH[] = ":path";
+  switch(frame->hd.type) {
+  case NGHTTP2_HEADERS:
+    if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
+      break;
+    }
+    stream_data = nghttp2_session_get_stream_user_data(session,
+                                                       frame->hd.stream_id);
+    if(stream_data->request_path) {
+      break;
+    }
+    if(namelen == sizeof(PATH) - 1 && memcmp(PATH, name, namelen) == 0) {
+      size_t j;
+      for(j = 0; j < valuelen && value[j] != '?'; ++j);
+      stream_data->request_path = percent_decode(value, j);
+    }
+    break;
+  }
+  return 0;
+}
+
+
+

We search :path header field in request headers and keep the +requested path in http2_stream_data object. In this example +program, we ignore :method header field and always treat the +request as GET request.

+

The on_frame_recv_callback() function is invoked when a frame is +fully received:

+
static int on_frame_recv_callback(nghttp2_session *session,
+                                  const nghttp2_frame *frame, void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  http2_stream_data *stream_data;
+  switch(frame->hd.type) {
+  case NGHTTP2_DATA:
+  case NGHTTP2_HEADERS:
+    /* Check that the client request has finished */
+    if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+      stream_data = nghttp2_session_get_stream_user_data(session,
+                                                         frame->hd.stream_id);
+      /* For DATA and HEADERS frame, this callback may be called after
+         on_stream_close_callback. Check that stream still alive. */
+      if(!stream_data) {
+        return 0;
+      }
+      return on_request_recv(session, session_data, stream_data);
+    }
+    break;
+  default:
+    break;
+  }
+  return 0;
+}
+
+
+

First we retrieve http2_stream_data object associated to the +stream in on_begin_headers_callback(). It is done using +nghttp2_session_get_stream_user_data(). If the requested path cannot +be served for some reasons (e.g., file is not found), we send 404 +response, which is done in error_reply(). Otherwise, we open +requested file and send its content. We send 1 header field +:status as a response header.

+

Sending content of a file is done in send_response() function:

+
static int send_response(nghttp2_session *session, int32_t stream_id,
+                         nghttp2_nv *nva, size_t nvlen, int fd)
+{
+  int rv;
+  nghttp2_data_provider data_prd;
+  data_prd.source.fd = fd;
+  data_prd.read_callback = file_read_callback;
+
+  rv = nghttp2_submit_response(session, stream_id, nva, nvlen, &data_prd);
+  if(rv != 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    return -1;
+  }
+  return 0;
+}
+
+
+

The nghttp2 library uses nghttp2_data_provider structure to +send entity body to the remote peer. The source member of this +structure is a union and it can be either void pointer or int which is +intended to be used as file descriptor. In this example server, we use +file descriptor. We also set file_read_callback() callback +function to read content of the file:

+
static ssize_t file_read_callback
+(nghttp2_session *session, int32_t stream_id,
+ uint8_t *buf, size_t length, int *eof,
+ nghttp2_data_source *source, void *user_data)
+{
+  int fd = source->fd;
+  ssize_t r;
+  while((r = read(fd, buf, length)) == -1 && errno == EINTR);
+  if(r == -1) {
+    return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+  }
+  if(r == 0) {
+    *eof = 1;
+  }
+  return r;
+}
+
+
+

If error happens while reading file, we return +NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE. This tells the library +to send RST_STREAM to the stream. When all data is read, set 1 to +*eof to tell the nghttp2 library that we have finished reading +file.

+

The nghttp2_submit_response() is used to send response to the remote +peer.

+

The on_stream_close_callback() function is invoked when the stream +is about to close:

+
static int on_stream_close_callback(nghttp2_session *session,
+                                    int32_t stream_id,
+                                    nghttp2_error_code error_code,
+                                    void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  http2_stream_data *stream_data;
+
+  stream_data = nghttp2_session_get_stream_user_data(session, stream_id);
+  remove_stream(session_data, stream_data);
+  delete_http2_stream_data(stream_data);
+  return 0;
+}
+
+
+

We destroy http2_stream_data object in this function since the +stream is about to close and we no longer use that object.

+
+

libevent-server.c¶

+
/*
+ * nghttp2 - HTTP/2.0 C Library
+ *
+ * Copyright (c) 2013 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 <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <err.h>
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include <event.h>
+#include <event2/event.h>
+#include <event2/bufferevent_ssl.h>
+#include <event2/listener.h>
+
+#include <nghttp2/nghttp2.h>
+
+#define OUTPUT_WOULDBLOCK_THRESHOLD (1 << 16)
+
+#define ARRLEN(x) (sizeof(x)/sizeof(x[0]))
+
+#define MAKE_NV(NAME, VALUE)                                            \
+  { (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1 }
+
+struct app_context;
+typedef struct app_context app_context;
+
+typedef struct http2_stream_data {
+  struct http2_stream_data *prev, *next;
+  char *request_path;
+  int32_t stream_id;
+  int fd;
+} http2_stream_data;
+
+typedef struct http2_session_data {
+  struct http2_stream_data root;
+  struct bufferevent *bev;
+  app_context *app_ctx;
+  nghttp2_session *session;
+  char *client_addr;
+  size_t handshake_leftlen;
+} http2_session_data;
+
+struct app_context {
+  SSL_CTX *ssl_ctx;
+  struct event_base *evbase;
+};
+
+static unsigned char next_proto_list[256];
+static size_t next_proto_list_len;
+
+static int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
+                         void *arg)
+{
+  *data = next_proto_list;
+  *len = next_proto_list_len;
+  return SSL_TLSEXT_ERR_OK;
+}
+
+/* Create SSL_CTX. */
+static SSL_CTX* create_ssl_ctx(const char *key_file, const char *cert_file)
+{
+  SSL_CTX *ssl_ctx;
+  ssl_ctx = SSL_CTX_new(SSLv23_server_method());
+  if(!ssl_ctx) {
+    errx(1, "Could not create SSL/TLS context: %s",
+         ERR_error_string(ERR_get_error(), NULL));
+  }
+  SSL_CTX_set_options(ssl_ctx,
+                      SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION |
+                      SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
+
+  if(SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file,
+                                 SSL_FILETYPE_PEM) != 1) {
+    errx(1, "Could not read private key file %s", key_file);
+  }
+  if(SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) {
+    errx(1, "Could not read certificate file %s", cert_file);
+  }
+
+  next_proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
+  memcpy(&next_proto_list[1], NGHTTP2_PROTO_VERSION_ID,
+         NGHTTP2_PROTO_VERSION_ID_LEN);
+  next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
+
+  SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
+  return ssl_ctx;
+}
+
+/* Create SSL object */
+static SSL* create_ssl(SSL_CTX *ssl_ctx)
+{
+  SSL *ssl;
+  ssl = SSL_new(ssl_ctx);
+  if(!ssl) {
+    errx(1, "Could not create SSL/TLS session object: %s",
+         ERR_error_string(ERR_get_error(), NULL));
+  }
+  return ssl;
+}
+
+static void add_stream(http2_session_data *session_data,
+                       http2_stream_data *stream_data)
+{
+  stream_data->next = session_data->root.next;
+  session_data->root.next = stream_data;
+  stream_data->prev = &session_data->root;
+  if(stream_data->next) {
+    stream_data->next->prev = stream_data;
+  }
+}
+
+static void remove_stream(http2_session_data *session_data,
+                          http2_stream_data *stream_data)
+{
+  stream_data->prev->next = stream_data->next;
+  if(stream_data->next) {
+    stream_data->next->prev = stream_data->prev;
+  }
+}
+
+static http2_stream_data* create_http2_stream_data
+(http2_session_data *session_data, int32_t stream_id)
+{
+  http2_stream_data *stream_data;
+  stream_data = malloc(sizeof(http2_stream_data));
+  memset(stream_data, 0, sizeof(http2_stream_data));
+  stream_data->stream_id = stream_id;
+  stream_data->fd = -1;
+
+  add_stream(session_data, stream_data);
+  return stream_data;
+}
+
+static void delete_http2_stream_data(http2_stream_data *stream_data)
+{
+  if(stream_data->fd != -1) {
+    close(stream_data->fd);
+  }
+  free(stream_data->request_path);
+  free(stream_data);
+}
+
+static http2_session_data* create_http2_session_data(app_context *app_ctx,
+                                                     int fd,
+                                                     struct sockaddr *addr,
+                                                     int addrlen)
+{
+  int rv;
+  http2_session_data *session_data;
+  SSL *ssl;
+  char host[NI_MAXHOST];
+  int val = 1;
+
+  ssl = create_ssl(app_ctx->ssl_ctx);
+  session_data = malloc(sizeof(http2_session_data));
+  memset(session_data, 0, sizeof(http2_session_data));
+  session_data->app_ctx = app_ctx;
+  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+  session_data->bev = bufferevent_openssl_socket_new
+    (app_ctx->evbase, fd, ssl,
+     BUFFEREVENT_SSL_ACCEPTING,
+     BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
+  session_data->handshake_leftlen = NGHTTP2_CLIENT_CONNECTION_HEADER_LEN;
+  rv = getnameinfo(addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
+  if(rv != 0) {
+    session_data->client_addr = strdup("(unknown)");
+  } else {
+    session_data->client_addr = strdup(host);
+  }
+
+  return session_data;
+}
+
+static void delete_http2_session_data(http2_session_data *session_data)
+{
+  http2_stream_data *stream_data;
+  SSL *ssl = bufferevent_openssl_get_ssl(session_data->bev);
+  fprintf(stderr, "%s disconnected\n", session_data->client_addr);
+  if(ssl) {
+    SSL_shutdown(ssl);
+  }
+  bufferevent_free(session_data->bev);
+  nghttp2_session_del(session_data->session);
+  for(stream_data = session_data->root.next; stream_data;) {
+    http2_stream_data *next = stream_data->next;
+    delete_http2_stream_data(stream_data);
+    stream_data = next;
+  }
+  free(session_data->client_addr);
+  free(session_data);
+}
+
+/* Serialize the frame and send (or buffer) the data to
+   bufferevent. */
+static int session_send(http2_session_data *session_data)
+{
+  int rv;
+  rv = nghttp2_session_send(session_data->session);
+  if(rv != 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    return -1;
+  }
+  return 0;
+}
+
+/* Read the data in the bufferevent and feed them into nghttp2 library
+   function. Invocation of nghttp2_session_mem_recv() may make
+   additional pending frames, so call session_send() at the end of the
+   function. */
+static int session_recv(http2_session_data *session_data)
+{
+  int rv;
+  struct evbuffer *input = bufferevent_get_input(session_data->bev);
+  size_t datalen = evbuffer_get_length(input);
+  unsigned char *data = evbuffer_pullup(input, -1);
+  rv = nghttp2_session_mem_recv(session_data->session, data, datalen);
+  if(rv < 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    return -1;
+  }
+  evbuffer_drain(input, rv);
+  if(session_send(session_data) != 0) {
+    return -1;
+  }
+  return 0;
+}
+
+static ssize_t send_callback(nghttp2_session *session,
+                             const uint8_t *data, size_t length,
+                             int flags, void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  struct bufferevent *bev = session_data->bev;
+  /* Avoid excessive buffering in server side. */
+  if(evbuffer_get_length(bufferevent_get_output(session_data->bev)) >=
+     OUTPUT_WOULDBLOCK_THRESHOLD) {
+    return NGHTTP2_ERR_WOULDBLOCK;
+  }
+  bufferevent_write(bev, data, length);
+  return length;
+}
+
+/* Returns nonzero if the string |s| ends with the substring |sub| */
+static int ends_with(const char *s, const char *sub)
+{
+  size_t slen = strlen(s);
+  size_t sublen = strlen(sub);
+  if(slen < sublen) {
+    return 0;
+  }
+  return memcmp(s + slen - sublen, sub, sublen) == 0;
+}
+
+/* Returns int value of hex string character |c| */
+static uint8_t hex_to_uint(uint8_t c)
+{
+  if('0' <= c && c <= '9') {
+    return c - '0';
+  }
+  if('A' <= c && c <= 'F') {
+    return c - 'A' + 10;
+  }
+  if('a' <= c && c <= 'f') {
+    return c - 'a' + 10;
+  }
+  return 0;
+}
+
+/* Decodes percent-encoded byte string |value| with length |valuelen|
+   and returns the decoded byte string in allocated buffer. The return
+   value is NULL terminated. The caller must free the returned
+   string. */
+static char* percent_decode(const uint8_t *value, size_t valuelen)
+{
+  char *res;
+
+  res = malloc(valuelen + 1);
+  if(valuelen > 3) {
+    size_t i, j;
+    for(i = 0, j = 0; i < valuelen - 2;) {
+      if(value[i] != '%' ||
+         !isxdigit(value[i + 1]) || !isxdigit(value[i + 2])) {
+        res[j++] = value[i++];
+        continue;
+      }
+      res[j++] = (hex_to_uint(value[i + 1]) << 4) + hex_to_uint(value[i + 2]);
+      i += 3;
+    }
+    memcpy(&res[j], &value[i], 2);
+    res[j + 2] = '\0';
+  } else {
+    memcpy(res, value, valuelen);
+    res[valuelen] = '\0';
+  }
+  return res;
+}
+
+static ssize_t file_read_callback
+(nghttp2_session *session, int32_t stream_id,
+ uint8_t *buf, size_t length, int *eof,
+ nghttp2_data_source *source, void *user_data)
+{
+  int fd = source->fd;
+  ssize_t r;
+  while((r = read(fd, buf, length)) == -1 && errno == EINTR);
+  if(r == -1) {
+    return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+  }
+  if(r == 0) {
+    *eof = 1;
+  }
+  return r;
+}
+
+static int send_response(nghttp2_session *session, int32_t stream_id,
+                         nghttp2_nv *nva, size_t nvlen, int fd)
+{
+  int rv;
+  nghttp2_data_provider data_prd;
+  data_prd.source.fd = fd;
+  data_prd.read_callback = file_read_callback;
+
+  rv = nghttp2_submit_response(session, stream_id, nva, nvlen, &data_prd);
+  if(rv != 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    return -1;
+  }
+  return 0;
+}
+
+const char ERROR_HTML[] = "<html><head><title>404</title></head>"
+  "<body><h1>404 Not Found</h1></body></html>";
+
+static int error_reply(nghttp2_session *session,
+                       http2_stream_data *stream_data)
+{
+  int rv;
+  int pipefd[2];
+  nghttp2_nv hdrs[] = {
+    MAKE_NV(":status", "404")
+  };
+
+  rv = pipe(pipefd);
+  if(rv != 0) {
+    warn("Could not create pipe");
+    rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+                                   stream_data->stream_id,
+                                   NGHTTP2_INTERNAL_ERROR);
+    if(rv != 0) {
+      warnx("Fatal error: %s", nghttp2_strerror(rv));
+      return -1;
+    }
+    return 0;
+  }
+  write(pipefd[1], ERROR_HTML, sizeof(ERROR_HTML) - 1);
+  close(pipefd[1]);
+  stream_data->fd = pipefd[0];
+  if(send_response(session, stream_data->stream_id, hdrs, ARRLEN(hdrs),
+                   pipefd[0]) != 0) {
+    close(pipefd[0]);
+    return -1;
+  }
+  return 0;
+}
+
+/* nghttp2_on_header_callback: Called when nghttp2 library emits
+   single header name/value pair. */
+static int on_header_callback(nghttp2_session *session,
+                              const nghttp2_frame *frame,
+                              const uint8_t *name, size_t namelen,
+                              const uint8_t *value, size_t valuelen,
+                              void *user_data)
+{
+  http2_stream_data *stream_data;
+  const char PATH[] = ":path";
+  switch(frame->hd.type) {
+  case NGHTTP2_HEADERS:
+    if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
+      break;
+    }
+    stream_data = nghttp2_session_get_stream_user_data(session,
+                                                       frame->hd.stream_id);
+    if(stream_data->request_path) {
+      break;
+    }
+    if(namelen == sizeof(PATH) - 1 && memcmp(PATH, name, namelen) == 0) {
+      size_t j;
+      for(j = 0; j < valuelen && value[j] != '?'; ++j);
+      stream_data->request_path = percent_decode(value, j);
+    }
+    break;
+  }
+  return 0;
+}
+
+static int on_begin_headers_callback(nghttp2_session *session,
+                                     const nghttp2_frame *frame,
+                                     void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  http2_stream_data *stream_data;
+
+  if(frame->hd.type != NGHTTP2_HEADERS ||
+     frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
+    return 0;
+  }
+  stream_data = create_http2_stream_data(session_data, frame->hd.stream_id);
+  nghttp2_session_set_stream_user_data(session, frame->hd.stream_id,
+                                       stream_data);
+  return 0;
+}
+
+/* Minimum check for directory traversal. Returns nonzero if it is
+   safe. */
+static int check_path(const char *path)
+{
+  /* We don't like '\' in url. */
+  return path[0] && path[0] == '/' &&
+    strchr(path, '\\') == NULL &&
+    strstr(path, "/../") == NULL &&
+    strstr(path, "/./") == NULL &&
+    !ends_with(path, "/..") && !ends_with(path, "/.");
+}
+
+static int on_request_recv(nghttp2_session *session,
+                           http2_session_data *session_data,
+                           http2_stream_data *stream_data)
+{
+  int fd;
+  nghttp2_nv hdrs[] = {
+    MAKE_NV(":status", "200")
+  };
+  char *rel_path;
+
+  if(!stream_data->request_path) {
+    if(error_reply(session, stream_data) != 0) {
+      return NGHTTP2_ERR_CALLBACK_FAILURE;
+    }
+    return 0;
+  }
+  fprintf(stderr, "%s GET %s\n", session_data->client_addr,
+          stream_data->request_path);
+  if(!check_path(stream_data->request_path)) {
+    if(error_reply(session, stream_data) != 0) {
+      return NGHTTP2_ERR_CALLBACK_FAILURE;
+    }
+    return 0;
+  }
+  for(rel_path = stream_data->request_path; *rel_path == '/'; ++rel_path);
+  fd = open(rel_path, O_RDONLY);
+  if(fd == -1) {
+    if(error_reply(session, stream_data) != 0) {
+      return NGHTTP2_ERR_CALLBACK_FAILURE;
+    }
+    return 0;
+  }
+  stream_data->fd = fd;
+
+  if(send_response(session, stream_data->stream_id, hdrs,
+                   ARRLEN(hdrs), fd) != 0) {
+    close(fd);
+    return NGHTTP2_ERR_CALLBACK_FAILURE;
+  }
+  return 0;
+}
+
+static int on_frame_recv_callback(nghttp2_session *session,
+                                  const nghttp2_frame *frame, void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  http2_stream_data *stream_data;
+  switch(frame->hd.type) {
+  case NGHTTP2_DATA:
+  case NGHTTP2_HEADERS:
+    /* Check that the client request has finished */
+    if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+      stream_data = nghttp2_session_get_stream_user_data(session,
+                                                         frame->hd.stream_id);
+      /* For DATA and HEADERS frame, this callback may be called after
+         on_stream_close_callback. Check that stream still alive. */
+      if(!stream_data) {
+        return 0;
+      }
+      return on_request_recv(session, session_data, stream_data);
+    }
+    break;
+  default:
+    break;
+  }
+  return 0;
+}
+
+static int on_stream_close_callback(nghttp2_session *session,
+                                    int32_t stream_id,
+                                    nghttp2_error_code error_code,
+                                    void *user_data)
+{
+  http2_session_data *session_data = (http2_session_data*)user_data;
+  http2_stream_data *stream_data;
+
+  stream_data = nghttp2_session_get_stream_user_data(session, stream_id);
+  remove_stream(session_data, stream_data);
+  delete_http2_stream_data(stream_data);
+  return 0;
+}
+
+static void initialize_nghttp2_session(http2_session_data *session_data)
+{
+  nghttp2_session_callbacks callbacks = {0};
+
+  callbacks.send_callback = send_callback;
+  callbacks.on_frame_recv_callback = on_frame_recv_callback;
+  callbacks.on_stream_close_callback = on_stream_close_callback;
+  callbacks.on_header_callback = on_header_callback;
+  callbacks.on_begin_headers_callback = on_begin_headers_callback;
+  nghttp2_session_server_new(&session_data->session, &callbacks, session_data);
+}
+
+/* Send HTTP/2.0 client connection header, which includes 24 bytes
+   magic octets and SETTINGS frame */
+static int send_server_connection_header(http2_session_data *session_data)
+{
+  nghttp2_settings_entry iv[1] = {
+    { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }
+  };
+  int rv;
+
+  rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE,
+                               iv, ARRLEN(iv));
+  if(rv != 0) {
+    warnx("Fatal error: %s", nghttp2_strerror(rv));
+    return -1;
+  }
+  return 0;
+}
+
+/* readcb for bufferevent after client connection header was
+   checked. */
+static void readcb(struct bufferevent *bev, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  if(session_recv(session_data) != 0) {
+    delete_http2_session_data(session_data);
+    return;
+  }
+}
+
+/* writecb for bufferevent. To greaceful shutdown after sending or
+   receiving GOAWAY, we check the some conditions on the nghttp2
+   library and output buffer of bufferevent. If it indicates we have
+   no business to this session, tear down the connection. If the
+   connection is not going to shutdown, we call session_send() to
+   process pending data in the output buffer. This is necessary
+   because we have a threshold on the buffer size to avoid too much
+   buffering. See send_callback(). */
+static void writecb(struct bufferevent *bev, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  if(evbuffer_get_length(bufferevent_get_output(bev)) > 0) {
+    return;
+  }
+  if(nghttp2_session_want_read(session_data->session) == 0 &&
+     nghttp2_session_want_write(session_data->session) == 0) {
+    delete_http2_session_data(session_data);
+    return;
+  }
+  if(session_send(session_data) != 0) {
+    delete_http2_session_data(session_data);
+    return;
+  }
+}
+
+/* eventcb for bufferevent */
+static void eventcb(struct bufferevent *bev, short events, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  if(events & BEV_EVENT_CONNECTED) {
+    fprintf(stderr, "%s connected\n", session_data->client_addr);
+    return;
+  }
+  if(events & BEV_EVENT_EOF) {
+    fprintf(stderr, "%s EOF\n", session_data->client_addr);
+  } else if(events & BEV_EVENT_ERROR) {
+    fprintf(stderr, "%s network error\n", session_data->client_addr);
+  } else if(events & BEV_EVENT_TIMEOUT) {
+    fprintf(stderr, "%s timeout\n", session_data->client_addr);
+  }
+  delete_http2_session_data(session_data);
+}
+
+/* readcb for bufferevent to check first 24 bytes client connection
+   header. */
+static void handshake_readcb(struct bufferevent *bev, void *ptr)
+{
+  http2_session_data *session_data = (http2_session_data*)ptr;
+  uint8_t data[24];
+  struct evbuffer *input = bufferevent_get_input(session_data->bev);
+  int readlen = evbuffer_remove(input, data, session_data->handshake_leftlen);
+  const char *conhead = NGHTTP2_CLIENT_CONNECTION_HEADER;
+
+  if(memcmp(conhead + NGHTTP2_CLIENT_CONNECTION_HEADER_LEN
+            - session_data->handshake_leftlen, data, readlen) != 0) {
+    delete_http2_session_data(session_data);
+    return;
+  }
+  session_data->handshake_leftlen -= readlen;
+  if(session_data->handshake_leftlen == 0) {
+    bufferevent_setcb(session_data->bev, readcb, writecb, eventcb, ptr);
+    /* Process pending data in buffer since they are not notified
+       further */
+    initialize_nghttp2_session(session_data);
+    if(send_server_connection_header(session_data) != 0) {
+      delete_http2_session_data(session_data);
+      return;
+    }
+    if(session_recv(session_data) != 0) {
+      delete_http2_session_data(session_data);
+      return;
+    }
+  }
+}
+
+/* callback for evconnlistener */
+static void acceptcb(struct evconnlistener *listener, int fd,
+                     struct sockaddr *addr, int addrlen, void *arg)
+{
+  app_context *app_ctx = (app_context*)arg;
+  http2_session_data *session_data;
+
+  session_data = create_http2_session_data(app_ctx, fd, addr, addrlen);
+  bufferevent_setcb(session_data->bev, handshake_readcb, NULL, eventcb,
+                    session_data);
+}
+
+static void start_listen(struct event_base *evbase, const char *service,
+                         app_context *app_ctx)
+{
+  int rv;
+  struct addrinfo hints;
+  struct addrinfo *res, *rp;
+
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_flags = AI_PASSIVE;
+#ifdef AI_ADDRCONFIG
+  hints.ai_flags |= AI_ADDRCONFIG;
+#endif // AI_ADDRCONFIG
+
+  rv = getaddrinfo(NULL, service, &hints, &res);
+  if(rv != 0) {
+    errx(1, NULL);
+  }
+  for(rp = res; rp; rp = rp->ai_next) {
+    struct evconnlistener *listener;
+    listener = evconnlistener_new_bind(evbase, acceptcb, app_ctx,
+                                       LEV_OPT_CLOSE_ON_FREE |
+                                       LEV_OPT_REUSEABLE, 16,
+                                       rp->ai_addr, rp->ai_addrlen);
+    if(listener) {
+      return;
+    }
+  }
+  errx(1, "Could not start listener");
+}
+
+static void initialize_app_context(app_context *app_ctx, SSL_CTX *ssl_ctx,
+                                   struct event_base *evbase)
+{
+  memset(app_ctx, 0, sizeof(app_context));
+  app_ctx->ssl_ctx = ssl_ctx;
+  app_ctx->evbase = evbase;
+}
+
+static void run(const char *service,
+                const char *key_file, const char *cert_file)
+{
+  SSL_CTX *ssl_ctx;
+  app_context app_ctx;
+  struct event_base *evbase;
+
+  ssl_ctx = create_ssl_ctx(key_file, cert_file);
+  evbase = event_base_new();
+  initialize_app_context(&app_ctx, ssl_ctx, evbase);
+  start_listen(evbase, service, &app_ctx);
+
+  event_base_loop(evbase, 0);
+
+  event_base_free(evbase);
+  SSL_CTX_free(ssl_ctx);
+}
+
+int main(int argc, char **argv)
+{
+  struct sigaction act;
+
+  if(argc < 4) {
+    fprintf(stderr, "Usage: libevent-server PORT KEY_FILE CERT_FILE\n");
+    exit(EXIT_FAILURE);
+  }
+
+  memset(&act, 0, sizeof(struct sigaction));
+  act.sa_handler = SIG_IGN;
+  sigaction(SIGPIPE, &act, NULL);
+
+  SSL_load_error_strings();
+  SSL_library_init();
+
+  run(argv[1], argv[2], argv[3]);
+  return 0;
+}
+
+
+
+
+ + +
+ +
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/search.html b/search.html index b88b43e1..52da7a9d 100644 --- a/search.html +++ b/search.html @@ -7,7 +7,7 @@ - Search — nghttp2 0.3.0-DEV documentation + Search — nghttp2 0.4.0-DEV documentation @@ -22,7 +22,7 @@ diff --git a/searchindex.js b/searchindex.js index 39212fab..3e8e9001 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{"":{NGHTTP2_ERR_INVALID_STATE:[3,1,1,""],NGHTTP2_ERR_HEADER_COMP:[3,1,1,""],NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:[3,1,1,""],nghttp2_settings_entry:[3,2,1,""],NGHTTP2_INTERNAL_ERROR:[3,1,1,""],NGHTTP2_PRI_LOWEST:[3,1,1,""],nghttp2_on_frame_recv_callback:[3,2,1,""],NGHTTP2_CLIENT_CONNECTION_HEADER_LEN:[3,1,1,""],nghttp2_goaway:[3,2,1,""],nghttp2_ping:[3,2,1,""],NGHTTP2_ERR_INVALID_FRAME:[3,1,1,""],nghttp2_frame_type:[3,2,1,""],NGHTTP2_ERR_INVALID_STREAM_ID:[3,1,1,""],nghttp2_select_next_protocol:[3,3,1,""],NGHTTP2_ERR_INVALID_HEADER_BLOCK:[3,1,1,""],nghttp2_session_callbacks:[3,2,1,""],NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS:[3,1,1,""],NGHTTP2_ERR_PROTO:[3,1,1,""],NGHTTP2_MAX_HEADER_TABLE_SIZE:[3,1,1,""],nghttp2_submit_window_update:[3,3,1,""],NGHTTP2_ERR_UNSUPPORTED_VERSION:[3,1,1,""],NGHTTP2_SETTINGS_ENABLE_PUSH:[3,1,1,""],nghttp2_window_update:[3,2,1,""],NGHTTP2_DATA:[3,1,1,""],nghttp2_frame_hd:[3,2,1,""],NGHTTP2_ERR_INVALID_STREAM_STATE:[3,1,1,""],nghttp2_on_header_callback:[3,2,1,""],NGHTTP2_FLAG_ACK:[3,1,1,""],NGHTTP2_STREAM_CLOSED:[3,1,1,""],NGHTTP2_SETTINGS_MAX:[3,1,1,""],nghttp2_on_begin_headers_callback:[3,2,1,""],NGHTTP2_MAX_WINDOW_SIZE:[3,1,1,""],nghttp2_headers_category:[3,2,1,""],nghttp2_error_code:[3,2,1,""],nghttp2_send_callback:[3,2,1,""],nghttp2_on_data_chunk_recv_callback:[3,2,1,""],NGHTTP2_ERR_START_STREAM_NOT_ALLOWED:[3,1,1,""],NGHTTP2_ERR_FLOW_CONTROL:[3,1,1,""],nghttp2_strerror:[3,3,1,""],nghttp2_gzip_inflate_del:[3,3,1,""],NGHTTP2_ERR_FATAL:[3,1,1,""],nghttp2_submit_goaway:[3,3,1,""],NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE:[3,1,1,""],NGHTTP2_ERR_NOMEM:[3,1,1,""],NGHTTP2_ERR_PAUSE:[3,1,1,""],nghttp2_session_client_new:[3,3,1,""],NGHTTP2_GOAWAY:[3,1,1,""],NGHTTP2_NO_ERROR:[3,1,1,""],NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS:[3,1,1,""],nghttp2_session_server_new2:[3,3,1,""],NGHTTP2_ERR_DEFERRED:[3,1,1,""],nghttp2_push_promise:[3,2,1,""],NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE:[3,1,1,""],nghttp2_session_get_outbound_queue_size:[3,3,1,""],NGHTTP2_PROTO_VERSION_ID_LEN:[3,1,1,""],NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS:[3,1,1,""],nghttp2_data_source_read_callback:[3,2,1,""],NGHTTP2_SETTINGS_TIMEOUT:[3,1,1,""],nghttp2_before_frame_send_callback:[3,2,1,""],NGHTTP2_ERR_WOULDBLOCK:[3,1,1,""],nghttp2_session_resume_data:[3,3,1,""],NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:[3,1,1,""],NGHTTP2_PRI_DEFAULT:[3,1,1,""],nghttp2_session_server_new:[3,3,1,""],NGHTTP2_CONTINUATION:[3,1,1,""],NGHTTP2_FLAG_END_PUSH_PROMISE:[3,1,1,""],NGHTTP2_ERR_INVALID_ARGUMENT:[3,1,1,""],NGHTTP2_ERR_FRAME_SIZE_ERROR:[3,1,1,""],NGHTTP2_ERR_GOAWAY_ALREADY_SENT:[3,1,1,""],NGHTTP2_HEADERS:[3,1,1,""],nghttp2_flag:[3,2,1,""],nghttp2_recv_callback:[3,2,1,""],NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:[3,1,1,""],NGHTTP2_HCAT_REQUEST:[3,1,1,""],NGHTTP2_FLAG_END_HEADERS:[3,1,1,""],nghttp2_gzip:[3,2,1,""],NGHTTP2_RST_STREAM:[3,1,1,""],nghttp2_rst_stream:[3,2,1,""],NGHTTP2_HCAT_HEADERS:[3,1,1,""],NGHTTP2_VERSION_NUM:[3,1,1,""],NGHTTP2_SETTINGS:[3,1,1,""],nghttp2_frame:[3,2,1,""],nghttp2_submit_push_promise:[3,3,1,""],nghttp2_session_mem_recv:[3,3,1,""],NGHTTP2_ERR_DEFERRED_DATA_EXIST:[3,1,1,""],NGHTTP2_CANCEL:[3,1,1,""],NGHTTP2_REFUSED_STREAM:[3,1,1,""],nghttp2_on_frame_send_callback:[3,2,1,""],NGHTTP2_ENHANCE_YOUR_CALM:[3,1,1,""],nghttp2_opt_set:[3,2,1,""],NGHTTP2_VERSION:[3,1,1,""],NGHTTP2_COMPRESSION_ERROR:[3,1,1,""],NGHTTP2_HCAT_PUSH_RESPONSE:[3,1,1,""],nghttp2_submit_rst_stream:[3,3,1,""],nghttp2_submit_headers:[3,3,1,""],NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE:[3,1,1,""],nghttp2_session_get_stream_user_data:[3,3,1,""],NGHTTP2_FLAG_PRIORITY:[3,1,1,""],nghttp2_nv:[3,2,1,""],nghttp2_on_invalid_frame_recv_callback:[3,2,1,""],nghttp2_version:[3,3,1,""],nghttp2_on_unknown_frame_recv_callback:[3,2,1,""],nghttp2_settings:[3,2,1,""],NGHTTP2_ERR_STREAM_CLOSED:[3,1,1,""],nghttp2_opt:[3,2,1,""],NGHTTP2_FLAG_END_STREAM:[3,1,1,""],NGHTTP2_ERR_CALLBACK_FAILURE:[3,1,1,""],NGHTTP2_FLOW_CONTROL_ERROR:[3,1,1,""],nghttp2_session_set_stream_user_data:[3,3,1,""],nghttp2_check_header_value:[3,3,1,""],NGHTTP2_ERR_STREAM_CLOSING:[3,1,1,""],nghttp2_check_header_name:[3,3,1,""],nghttp2_info:[3,2,1,""],NGHTTP2_PROTO_VERSION_ID:[3,1,1,""],nghttp2_settings_id:[3,2,1,""],nghttp2_session_send:[3,3,1,""],NGHTTP2_PROTOCOL_ERROR:[3,1,1,""],nghttp2_gzip_inflate:[3,3,1,""],nghttp2_session_upgrade:[3,3,1,""],nghttp2_session_del:[3,3,1,""],NGHTTP2_ERR_INSUFF_BUFSIZE:[3,1,1,""],nghttp2_error:[3,2,1,""],nghttp2_on_frame_not_send_callback:[3,2,1,""],nghttp2_session_get_effective_recv_data_length:[3,3,1,""],nghttp2_submit_response:[3,3,1,""],NGHTTP2_CLIENT_CONNECTION_HEADER:[3,1,1,""],NGHTTP2_FLAG_NONE:[3,1,1,""],nghttp2_session_terminate_session:[3,3,1,""],nghttp2_submit_settings:[3,3,1,""],NGHTTP2_HCAT_RESPONSE:[3,1,1,""],NGHTTP2_PING:[3,1,1,""],NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE:[3,1,1,""],nghttp2_priority:[3,2,1,""],nghttp2_session_want_read:[3,3,1,""],NGHTTP2_VERSION_AGE:[3,1,1,""],NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE:[3,1,1,""],NGHTTP2_CONNECT_ERROR:[3,1,1,""],nghttp2_submit_data:[3,3,1,""],nghttp2_on_stream_close_callback:[3,2,1,""],NGHTTP2_PUSH_PROMISE:[3,1,1,""],nghttp2_data_provider:[3,2,1,""],NGHTTP2_ERR_PUSH_DISABLED:[3,1,1,""],nghttp2_session_recv:[3,3,1,""],nghttp2_session_get_effective_local_window_size:[3,3,1,""],NGHTTP2_INITIAL_WINDOW_SIZE:[3,1,1,""],NGHTTP2_ERR_EOF:[3,1,1,""],NGHTTP2_WINDOW_UPDATE:[3,1,1,""],NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS:[3,1,1,""],nghttp2_session_want_write:[3,3,1,""],nghttp2_submit_priority:[3,3,1,""],nghttp2_session_client_new2:[3,3,1,""],nghttp2_headers:[3,2,1,""],nghttp2_session:[3,2,1,""],nghttp2_session_get_stream_effective_local_window_size:[3,3,1,""],NGHTTP2_ERR_GZIP:[3,1,1,""],nghttp2_is_fatal:[3,3,1,""],nghttp2_submit_ping:[3,3,1,""],NGHTTP2_FRAME_SIZE_ERROR:[3,1,1,""],nghttp2_gzip_inflate_new:[3,3,1,""],NGHTTP2_ERR_STREAM_SHUT_WR:[3,1,1,""],NGHTTP2_PRIORITY:[3,1,1,""],nghttp2_submit_request:[3,3,1,""],nghttp2_session_get_stream_effective_recv_data_length:[3,3,1,""],nghttp2_pack_settings_payload:[3,3,1,""],nghttp2_data:[3,2,1,""],nghttp2_data_source:[3,2,1,""],nghttp2_nv_compare_name:[3,3,1,""]},nghttp2_session_callbacks:{before_frame_send_callback:[3,0,1,""],on_invalid_frame_recv_callback:[3,0,1,""],on_stream_close_callback:[3,0,1,""],on_data_chunk_recv_callback:[3,0,1,""],on_begin_headers_callback:[3,0,1,""],send_callback:[3,0,1,""],on_unknown_frame_recv_callback:[3,0,1,""],on_frame_recv_callback:[3,0,1,""],on_header_callback:[3,0,1,""],on_frame_not_send_callback:[3,0,1,""],on_frame_send_callback:[3,0,1,""],recv_callback:[3,0,1,""]},nghttp2_frame:{push_promise:[3,0,1,""],settings:[3,0,1,""],ping:[3,0,1,""],rst_stream:[3,0,1,""],priority:[3,0,1,""],headers:[3,0,1,""],goaway:[3,0,1,""],window_update:[3,0,1,""],data:[3,0,1,""],hd:[3,0,1,""]},nghttp2_ping:{hd:[3,0,1,""]},nghttp2_data_provider:{source:[3,0,1,""],read_callback:[3,0,1,""]},nghttp2_priority:{pri:[3,0,1,""],hd:[3,0,1,""]},nghttp2_settings_entry:{settings_id:[3,0,1,""],value:[3,0,1,""]},nghttp2_window_update:{hd:[3,0,1,""],window_size_increment:[3,0,1,""]},nghttp2_frame_hd:{stream_id:[3,0,1,""],length:[3,0,1,""],type:[3,0,1,""],flags:[3,0,1,""]},nghttp2_info:{age:[3,0,1,""],version_str:[3,0,1,""],version_num:[3,0,1,""],proto_str:[3,0,1,""]},nghttp2_rst_stream:{error_code:[3,0,1,""],hd:[3,0,1,""]},nghttp2_nv:{valuelen:[3,0,1,""],namelen:[3,0,1,""],name:[3,0,1,""],value:[3,0,1,""]},nghttp2_headers:{nvlen:[3,0,1,""],pri:[3,0,1,""],hd:[3,0,1,""],nva:[3,0,1,""],cat:[3,0,1,""]},nghttp2_opt_set:{no_auto_stream_window_update:[3,0,1,""],peer_max_concurrent_streams:[3,0,1,""],no_auto_connection_window_update:[3,0,1,""]},nghttp2_goaway:{opaque_data:[3,0,1,""],error_code:[3,0,1,""],opaque_data_len:[3,0,1,""],hd:[3,0,1,""],last_stream_id:[3,0,1,""]},nghttp2_data_source:{fd:[3,0,1,""],ptr:[3,0,1,""]},nghttp2_push_promise:{promised_stream_id:[3,0,1,""],nvlen:[3,0,1,""],nva:[3,0,1,""],hd:[3,0,1,""]},nghttp2_settings:{niv:[3,0,1,""],hd:[3,0,1,""],iv:[3,0,1,""]}},terms:{my_obj:[3,6],nghttp2_io_flag:6,nghttp2_cancel:[3,6],opt_set:[3,6],prefix:[2,6,3],nghttp2_session_get_stream_effective_local_window_s:[3,6],"const":[2,6,5,3],nghttp2_submit_:[2,5],under:[3,6,4],bufferevent_getfd:5,spec:[3,6],merchant:[2,6,5,1],digit:5,"void":[2,6,5,3],bufferevent_ssl:[2,5],initialize_nghttp2_setup:[2,5],verif:5,servic:2,warnx:[2,5],on_stream_close_callback:[2,6,5,3],direct:4,ssl_op_no_session_resumption_on_renegoti:[2,5],neg:[3,6],nghttp2_err_insuff_bufs:[3,6],"new":[2,6,4,5,3],tatsuhiro:[0,1,2,4,5,6],nghttp2_session_resume_data:[3,6],ipproto_tcp:[2,5],abov:[2,1,3,4,5,6],initialize_app_context:2,here:[2,6,4,5,3],met:[2,6,5,3],path:[2,4,5],settings_timeout:[3,6],interpret:[3,6],nextprotoneg:[3,6],sslv23_server_method:2,permit:[2,6,5,1],nghttp2_submit_prior:[3,6],aka:[3,6,4],nghttp2_err_gzip:[3,6],nghttp2_frame:[2,6,5,3],bufferevent_ssl_connect:5,substr:2,bev_event_error:[2,5],printabl:5,unit:4,describ:[2,6,5,3],would:[3,6],overhead:4,asset:4,nghttp2_on_invalid_frame_recv_callback:[3,6],nghttp2_version:[3,6,1],type:[0,2,3,4,5,6],tell:[2,6,5,3],relat:[2,5],notic:[2,6,5,1],warn:2,ssl_shutdown:[2,5],herebi:[2,6,5,1],unpack:[3,6],must:[2,6,4,5,3],word:[3,6],err:[2,5],exit_failur:[2,5],setup:[2,5],work:[2,4],lev_opt_close_on_fre:2,nghttp2_flag_ack:[3,6],root:[2,4],syn_repli:[3,6],defer:[2,6,5,3],give:[3,6],indic:[2,6,4,5,3],want:[2,6,5,3],unsign:[2,6,5,3],nghttp2_settings_flow_control_opt:[3,6],end:[2,6,5,3],datalen:[2,5],how:5,nghttp2_err_fat:[3,6],nghttp2_frame_typ:[3,6],updat:[3,6],nghttp2_msg_more:6,after:[2,6,4,5,3],badli:[3,6],demonstr:5,request_path:2,attempt:[3,6],third:[2,6,5,3],opaqu:[3,6],exclud:[3,6],receiv:[2,6,5,3],first:[2,6,4,5,3],order:[2,6,4,3],frontend:4,over:[2,4,5],becaus:[2,6,5,3],eagain:[2,5],vari:4,fit:[2,6,5,1],fwrite:5,deflate_s:4,hidden:[3,6],them:[2,6,5,3],thei:[2,6,4,5,3],safe:[2,6,3],"break":[2,6,5,3],promis:[3,6],choic:[3,6],ai_addr:2,timeout:[2,5],each:[2,6,4,5,3],debug:[3,6,5],side:[2,6,3],mean:[3,6,4,5],slen:2,protocol_error:[3,6],http2_stream_data:[2,5],nghttp2_session_server_new2:[3,6],network:[2,5],content:[0,4,2],end_stream:[3,6,4],situat:[2,5],free:[2,6,5,1,3],spdy:[3,6,4],openssl:[2,4,5],nghttp2_version_num:[3,6,1],sigact:[2,5],rang:[3,6,4],restrict:[2,6,5,1],nghttp2_protocol_error:[3,6],alreadi:[2,6,5,3],primari:[3,6],nghttp2_max_header_table_s:[3,6],too:[2,6,3],memcmp:2,draft:[0,6,4,3],listen:[2,4],tool:[0,6,4,3],travers:2,compressor:4,target:[3,6,4],provid:[2,1,3,4,5,6],project:[0,4],matter:[3,6],nghttp2_continu:[3,6],increment:[3,6],nghttp2_session_recv:[3,6],nghttp2_session_get_stream_effective_recv_data_length:[3,6],transmit:[3,6,5],sig_ign:[2,5],shall:[2,6,5,1],object:[2,6,4,5,3],writecb:[2,5],nghttp2_settings_timeout:[3,6],simplic:5,don:[2,6,3],hex_to_uint:2,doc:4,flow:[3,6],doe:[2,6,4,5,3],nghttp2_gzip_inflate_new:[3,6],section:[3,6],on_invalid_frame_recv_callback:[3,6],bev_event_eof:[2,5],pkg:4,identifi:[2,6,5,3],bufferevent_setcb:[2,5],involv:[3,6],explain:5,configur:[3,6,4],apach:4,nghttp2_err_invalid_stream_id:[3,6],busi:[2,5],oct:4,nghttp2_err_proto:[3,6],authoritylen:5,stop:[2,5],end_head:[3,6,4],evbuffer_drain:[2,5],bar:4,ai_pass:2,ietf:[0,6,4,3],baz:4,push_promis:[2,6,3],"public":[0,6,4,3],nghttp2_strerror:[2,6,5,3],nghttp2_gzip_inflate_del:[3,6],bufferevent_ssl_accept:2,nul:[3,6],result:[2,6,5,3],respons:[2,6,4,5,3],fail:[3,6],key_fil:2,subject:[2,6,5,1],said:[3,6],figur:4,bev_opt_close_on_fre:[2,5],accord:[3,6],extens:[4,5],advertis:[2,5],setsockopt:[2,5],against:[3,6],ssl_ctx_use_certificate_chain_fil:2,header_t:4,logic:2,browser:4,com:[0,6,4,3],int32_t:[2,6,5,3],assum:[3,6],duplic:[3,6],reciev:5,liabil:[2,6,5,1],evbuffer_get_length:[2,5],union:[0,6,3,2],max_deflate_s:4,been:[2,6,5,3],trigger:[3,6],interest:[2,4,5],basic:4,futur:[3,6],tini:5,life:2,regul:[2,5],argument:[2,6,4,5,3],ewouldblock:[2,5],ssl_op_no_compress:[2,5],nghttp2_settings_initial_window_s:[3,6],zlib:4,nghttp2_on_begin_headers_callback:[3,6,5],bev_event_timeout:[2,5],bufferevent_socket_connect_hostnam:5,nghttp2_set:[3,6],promised_stream_id:[3,6],conf:4,sever:[2,6,4,5,3],perform:[2,6,4,3],make:[2,6,4,3],transpar:[3,6],headlen:[3,6],split:[3,6],version_str:[3,6],nghttp2_on_stream_close_callback:[3,6,5],complet:[2,6,5,3],start_listen:2,bufferevent_openssl_get_ssl:[2,5],nghttp2_err_deferred_data_exist:[3,6],ssl_ctx_new:[2,5],zlib1g:4,ownership:[3,6],niv:[3,6,4],thu:[2,6,3],nghttp2_session_get_effective_local_window_s:[3,6],client:[0,2,3,4,5,6],thi:[0,1,2,3,4,5,6],endif:[2,6,1],gzip:[3,6,4],opaque_data:[3,6,4],protocol:[0,2,3,4,5,6],just:[2,6,4,5,3],"0x01":4,initiate_connect:5,ifdef:[2,6],previous:[3,6],easi:4,els:[2,5],applic:[2,6,4,5,3],initialize_nghttp2_sess:[2,5],specif:[2,6,5,3],arbitrari:[3,6],http2_session_data:[2,5],client_addr:2,manual:4,html:[0,6,4,3,2],tcp_nodelai:[2,5],unnecessari:5,underli:[2,5],www:[3,6],right:[2,6,5,1],deal:[2,6,5,1,3],successfulli:[2,6,5,3],transmiss:[2,6,5,3],ni_numerichost:2,bottom:[3,6],nghttp2_data_source_read_callback:[3,6],buffer:[2,6,4,5,3],condit:[2,6,5,1,3],foo:4,localhost:4,particular:[2,6,5,1,3],sensibl:[3,6],repositori:[2,5],peer:[2,6,5,3],post:[3,6,4],decompressor:4,inlen_ptr:[3,6],nghttp2_submit_data:[3,6],nghttp2_settings_max_concurrent_stream:[2,6,5,3],produc:[3,6],evbuff:[2,5],encod:[2,6,4,3],down:[2,5],nghttp2_before_frame_send_callback:[3,6,5],errx:[2,5],git:[0,6,4,3],session_send:[2,5],wai:[3,6,4],support:[2,6,4,5,3],verbos:4,call:[2,6,4,5,3],fork:4,head:[2,6,3],form:[3,6],offer:4,bev_event_connect:[2,5],"true":4,hddeflat:4,ssl_ctx_free:[2,5],maximum:[3,6,4],until:[3,6],deafult:4,autoconf:4,emit:[2,6,5,3],nghttp2_initial_window_s:[3,6],featur:4,httpbi:[0,6,4,3],"abstract":[2,5],unreleas:4,exist:[3,6,4],ai_flag:2,ends_with:2,check:[2,6,5,3],delete_http2_session_data:[2,5],when:[2,6,4,5,3],role:[2,6,5,3],nghttp2_check_header_valu:[3,6],send_client_connection_head:5,unlimit:[3,6],intend:2,af_unspec:[2,5],nghttp2_max_window_s:[3,6],technot:[3,6],max_siz:4,evconnlistener_new_bind:2,longer:[2,4],nghttp2_check_header_nam:[3,6],ignor:[2,6,3],time:[2,6,4,3],push:[3,6,4],skip:[3,6],evbuffer_remov:2,nghttp2_on_frame_recv_callback:[3,6,5],nghttp2ver_h:1,decid:[3,6],create_ssl_ctx:[2,5],depend:[2,5],readabl:5,sourc:[0,6,5,3,2],string:[2,6,4,5,3],nghttp2_settings_enable_push:[3,6],level:[2,6,3],did:[3,6,5],item:4,settings_id:[3,6],conhead:2,upper:[3,6],sign:4,port:[2,4,5],appear:[3,6,4],event_base_fre:[2,5],current:[2,6,4,3],gener:[3,6,4],address:4,nghttp2_submit_rst_stream:[2,6,3],connect_error:[3,6],queue:[2,6,5,3],behav:[3,6],ourselv:[2,5],nghttp2_err_goaway_already_s:[3,6],regardless:[3,6],extra:[4,5],modul:4,prefer:[3,6],instal:4,hdinflat:4,memori:[2,6,4,5,3],strdup:2,prev:2,reorder:[3,6,5],rst_stream:[2,6,5,3],ctype:2,nghttp2_submit_window_upd:[3,6],prepar:[3,6],stream_user_data:[3,6,5],cat:[2,6,5,3],descriptor:[2,6,3],can:[2,6,4,5,3],http2:[0,6,4,3],purpos:[2,6,5,1],uf_path:5,claim:[2,6,5,1],stream:[2,6,4,5,3],agent:4,critic:[3,6],abort:[3,6],tabl:[3,6,4],nghttp2_header:[2,6,5,3],occur:[3,6],alwai:[2,6,3],multipl:[2,6,5,3],charset:4,ping:[3,6],write:[2,4,5],opt_set_mask:[3,6],max:5,intrus:2,mai:[2,6,4,5,3],acceptcb:2,data:[2,6,4,5,3],autotool:4,stdin:4,inform:[2,6,4,5,3],"switch":[2,4,5],aaaabaaaagqaaaahaad__w:4,talk:[2,4],nghttp2_err_stream_shut_wr:[3,6],size_t:[2,6,5,3],nghttp2_err_unsupported_vers:[3,6],still:[2,6,4,3],pointer:[2,6,3],entiti:2,disconnect:[2,5],precondit:[3,6],tort:[2,6,5,1],window:[3,6],main:[2,5],non:[2,6,4,5,3],recal:5,initi:[2,6,5,3],nghttp2_submit_head:[3,6],nghttp2_on_header_callback:[2,6,5,3],name:[2,6,4,5,3],version_num:[3,6],config:4,no_error:4,drop:[2,6,5,3],replac:[3,6],individu:[3,6],continu:[2,6,4,5,3],event_base_loop:[2,5],turoti:5,happen:[2,4,5],ai_addrlen:2,space:[3,6,4],output_length:4,nghttp2_flag_end_push_promis:[3,6],earlier:[2,4,5],event_base_new:[2,5],argv:[2,5],org:[0,6,4,3],"byte":[2,6,4,5,3],argc:[2,5],care:[3,6],nghttp2_opt_no_auto_connection_window_upd:[3,6],nghttp2ver:[0,6,1,3],"88448504252dd5918485":4,befor:[2,6,4,5,3],thing:[2,6,5,3],nghttp2_flag_non:[2,6,5,3],place:[3,6],evdns_base_new:5,oper:[3,6,4],directli:[2,6,5,3],onc:[3,6],arrai:[3,6,4,5],yourself:4,nghttp2_is_fat:[3,6],nghttp2_flow_control_error:[3,6],submit:[3,6,5],on_frame_recv_callback:[2,6,5,3],open:[2,6,4,3],size:[2,6,4,3],avail:[2,6,4,5,3],given:[3,6],necessarili:[3,6],sigpip:[2,5],internal_error:[3,6],conveni:[3,6],ssl_ctx:[2,6,5,3],copi:[2,6,5,1,3],specifi:[2,6,4,5,3],github:[0,4],holder:[2,6,5,1],than:[2,6,4,3],serv:2,wide:2,nghttp2_session_get_outbound_queue_s:[3,6],were:[2,5],posit:[3,6],read_callback:[2,6,3],enhance_your_calm:[3,6],lowest:[3,6],sai:[3,6],pri:[3,6],ani:[2,1,3,4,5,6],deliv:[3,6],bitwis:[3,6],event_bas:[2,5],nghttp2_flag_prior:[3,6],destroi:[2,5],payloadlen:[3,6],note:[2,6,4,5,3],take:[2,6,4,5,3],properti:[2,5],noth:[3,6],begin:5,sure:[2,4,5],normal:[3,6],track:[2,4,5],compress:[0,4],nghttp2_hcat_request:[2,6,5,3],pathlen:5,sublicens:[2,6,5,1],pair:[2,6,4,5,3],http2_select:[3,6],later:[2,6,5,3],gracefulli:5,show:[4,5],unprocess:[2,5],concurr:[2,6,3],permiss:[2,6,5,1],threshold:2,onli:[2,6,4,5,3],written:[2,6,4,5,3],"4e5535a027780":4,overwritten:[3,6],reset:5,variou:[3,6],get:[2,6,4,5,3],outlen:[3,6,5],ssl:[2,6,4,5,3],cannot:[2,6,3],nghttpd:4,requir:[0,6,4,3],nghttp2_set_stream_user_data:2,multi:4,detect:[3,6,4],"import":4,fcntl:2,pipefd:2,bump:[3,6],evdns_bas:5,typedef:[0,6,5,3,2],submit_request:5,region:[3,6],"0x000300":1,contract:[2,6,5,1],tutori:[0,5,2],deflatehd:4,mani:[3,6],nghttp2_data_provid:[2,6,3],unistd:[2,5],nghttp2_err_too_many_inflight_set:[3,6],cancel:[3,6],damag:[2,6,5,1],header_table_s:4,nghttp2_settings_max:[3,6],netdb:2,nghttp2_on_unknown_frame_recv_callback:[3,6],nghttp2_opt:[3,6],those:[2,6,5,3],"case":[2,6,4,5,3],hdr:[2,4,5],invok:[2,6,5,3],invoc:[2,6,3],on_data_chunk_recv_callback:[3,6,5],stdout:[4,5],ascii:[3,6],develop:[0,4],author:[2,6,4,5,1],bev_opt_defer_callback:[2,5],alphabet:[3,6],same:[2,6,4,5,3],ssl_library_init:[2,5],binari:5,pac:4,document:[0,1,2,4,5,6],finish:[2,5],decompress:[3,6,4],handshake_leftlen:2,extern:6,postpon:[3,6],macro:[0,6,1,3],without:[2,1,3,4,5,6],nghttp2_push_promis:[3,6],event2:[2,5],nghttp2_err_def:[3,6],nghttp2_submit_set:[2,6,5,3],execut:4,multiplex:[2,4],struct:[0,6,5,3,2],hint:2,except:[3,6],identif:[3,6],nghttp2_select_next_protocol:[3,6,5],real:5,read:[2,6,4,5,3],nghttp2_version_ag:[3,6],test:[0,4],next_proto_cb:2,integ:[3,6],server:[0,2,3,4,5,6],either:[2,6,3],output:[2,6,4,5,3],manag:[2,6,3],stream_clos:[3,6],ssl_ctx_set_next_protos_advertised_cb:2,handshak:[2,5],nonzero:[2,6,3],easili:5,exit:[2,5],refer:[0,6,4,3],base64url:[3,6],nghttp2_session_server_new:[2,6,3],fulli:2,getnameinfo:2,src:4,inflater_ptr:[3,6],ack:[3,6,4],dnsbase:5,settings_payload:[3,6],act:[2,5],routin:[2,5],no_auto_stream_window_upd:[3,6],least_vers:[3,6],error_repli:2,insuffici:[3,6],b2a_hex:4,nghttp2_hcat_respons:[3,6,5],hex:[2,4],start:[2,6,4,5,3],nghttp2_err_stream_clos:[3,6],low:[3,6],lot:[3,6],ipv6:4,strictli:[3,6],next_proto_list:2,nghttp2_proto_version_id_len:[2,6,3],nghttp2_err_invalid_st:[3,6],possibl:[2,6,5,3],"default":[2,6,4,3],hpack:[0,4],err_get_error:[2,5],expect:4,creat:[2,6,4,5,3],mainli:[3,6],decreas:[3,6],file:[2,1,3,4,5,6],nghttp2_err_invalid_header_block:[3,6],fill:2,denot:[3,6,5],functypedef:6,googl:4,field:[2,6,4,5,3],valid:[3,6,4],nghttp2_prioriti:[3,6],print_head:5,you:[2,6,4,5,3],sequenc:[2,6,4,5,3],reduc:[3,6],cunit:4,directori:[2,4,5],mask:[3,6],represent:[3,1],all:[2,6,5,1,3],on_unknown_frame_recv_callback:[3,6],illustr:4,nghttp2_err_start_stream_not_allow:[3,6],lack:[3,6],follow:[2,1,3,4,5,6],ptr:[2,6,5,3],app_cont:2,uint8_t:[2,6,5,3],readcb:[2,5],program:[0,4,5,2],bufferevent_writ:[2,5],uf_queri:5,far:[2,5],settings_header_table_s:[3,6,4],nghttp2_client_connection_header_len:[2,6,5,3],failur:[3,6],veri:[3,6,5],no_auto_connection_window_upd:[3,6],"__cplusplu":6,list:[2,6,3],nghttp2_headers_categori:[3,6],adjust:[3,6],stderr:[2,4,5],small:[3,6],session_recv:2,zero:[3,6],pass:[3,6,5],further:[2,6,5,3],what:[3,6,4],sub:2,sun:4,sum:4,delet:5,version:[0,6,4,1,3],method:[2,6,4,5,3],libjansson:4,percentage_of_original_s:4,excess:2,modifi:[2,6,4,5,1],valu:[2,6,4,5,3],search:2,ai_addrconfig:2,nghttp2_err_push_dis:[3,6],prior:4,amount:[2,5],action:[2,6,5,1,3],via:[2,6,4,5,3],primit:5,famili:[2,5],establish:[2,5],select:[3,6,4,5],regist:2,libev:[0,4,5,2],taken:[3,6],minor:[3,1],more:[2,6,4,5,3],tsujikawa:[2,6,5,1],nghttp2_settings_header_table_s:[3,6],nghttp2_pri_default:[3,6,5],flag:[2,6,4,5,3],sens:[3,6],known:[3,6],nghttp2_err_wouldblock:[2,6,5,3],endpoint:[3,6,4],dev:[4,1],remain:[2,6,5,3],share:[3,6,4],accept:[2,6,4,3],minimum:2,ssl_op_al:[2,5],create_ssl:[2,5],strlen:[2,5],huge:[2,5],netinet:[2,5],secur:4,anoth:[3,6],serveraddr:4,reject:[3,6],sec9:[3,6],simpl:[2,6,5,3],resourc:[0,6,4,5,3],referenc:4,variant:[3,6],spdylai:4,associ:[2,1,3,4,5,6],"short":[2,5],caus:[3,6],callback:[2,6,5,3],alpn:[3,6,4],authroiti:5,hypertext:[0,4],libcunit1:4,through:[2,4],left:[3,6],paramet:[3,6,5],style:4,nghttp2_hcat_push_respons:[3,6],pend:[2,6,5,3],nghttp2_err_eof:[3,6],progoram:5,valuelen:[2,6,5,3],"0x010203":[3,1],"return":[2,6,4,5,3],check_path:2,synopsi:[2,5],nghttp2_initial_max_concurrent_stream:[3,6],readlen:2,nghttp2_err_callback_failur:[2,6,5,3],tear:[2,5],achiev:[2,6,3],found:[2,6,3],trailer:[3,6],nghttp2_on_frame_send_callback:[3,6],monoton:5,realli:5,connect:[2,1,3,4,5,6],field_set:5,event:[2,6,5,1],app_ctx:2,publish:[2,6,5,1],payload:[3,6],etag:4,print:[4,5],on_frame_not_send_callback:[3,6],proxi:[0,4],differ:[3,6],effect:[3,6],reason:[2,6,3],base:[2,4,5],put:[3,6],nghttp2_session_mem_recv:[2,6,5,3],nghttp2_flag:[3,6],recv:4,thread:[2,4],omit:[3,6,5],nghttp2_err_invalid_stream_st:[3,6],assign:[2,6,5,3],feed:[2,5],major:[3,1],notifi:2,prevent:[3,6],number:[2,6,1,3],"0x8":[3,6],done:[2,4,5],construct:[3,6],stdlib:6,nghttp2_internal_error:[2,6,3],script:4,data_prd:[2,6,3],nghttp2_session_get_stream_user_data:[2,6,5,3],least:[3,6,4],scheme:[4,5],store:[2,6,5,3],input_length:4,memset:[2,5],option:[2,6,4,5,3],similarli:[3,6],nghttp2_client_connection_head:[2,6,5,3],pars:5,kind:[2,6,5,1,3],doubli:2,remot:[2,6,4,5,3],remov:[2,6,3],bridg:4,ai_next:2,consumpt:[2,5],nghttp2_error:[3,6],window_size_incr:[3,6,4],lib_error_cod:[3,6],arrlen:[2,5],packag:4,"null":[2,6,5,3],syn_stream:[3,6],sell:[2,6,5,1],outbound:[3,6],equival:[3,6],afram:[3,6],also:[2,6,4,5,3],build:[0,4,5],nghttp2_err_frame_size_error:[3,6],make_nv:[2,5],distribut:[2,6,5,1],reacb:5,reach:[3,6],chart:[3,6],most:[3,6],vnu:4,charg:[2,6,5,1],addr:2,"01881f3468e5891afcbf83868a3d856659c62e3f":4,compar:[3,6,5],frame_size_error:[3,6,4],session:[2,6,5,3],nghttp2_submit_push_promis:[3,6],copyright:[2,6,5,1],refused_stream:[3,6],nghttp2_opt_no_auto_stream_window_upd:[3,6],queu:[2,6,5,3],express:[2,6,5,1],window_upd:[3,6,4],liabl:[2,6,5,1],before_frame_send_callback:[3,6,5],retreiv:5,crt:2,certif:[2,4,5],set:[2,6,4,5,3],seq:4,sep:4,ousid:4,remove_stream:2,nghttp2_submit_goawai:[3,6],arg:[2,6,5,3],close:[2,6,4,5,3],analog:[3,6],strchr:2,someth:[3,6],won:[2,6,3],hold:[3,6],nghttp2_on_data_chunk_recv_callback:[3,6,5],numer:[3,6,1],percent_decod:2,both:[2,6,4,5,3],last:[3,6,4],delimit:4,nghttp2_session_want_writ:[2,6,5,3],tempor:[3,6],context:[2,6,4,5,3],compression_error:[3,6],whole:[3,6],simpli:[2,5],point:[2,6,5,3],header:[0,2,3,4,5,6],shutdown:[2,6,5,3],suppli:[3,6],nghttp2_session:[2,6,5,3],backend:4,due:[3,6],empti:[2,6,4,5,3],send_respons:2,whom:[2,6,5,1],stdint:6,add_stream:2,flight:[3,6],nghttp2_err_nomem:[3,6],settings_enable_push:[3,6,4],nghttp2_session_terminate_sess:[3,6,5],buflen:[3,6],func:6,next_proto_list_len:2,look:[2,5],"while":[2,6,5,3],behavior:[3,6],error:[2,6,4,5,3],loop:[2,5],malloc:[2,5],nghttp2_session_callback:[2,6,5,3],readi:2,user_data:[2,6,5,3],itself:[2,6,5,3],flow_control_error:[3,6],grant:[2,6,5,1],belong:[3,6],create_http2_session_data:[2,5],decod:[2,6,3],uf_schema:5,mytyp:[3,6],inflat:[3,6,4],alert:4,moment:4,user:[3,6,4,5],implement:[0,2,3,4,5,6],nghttp2_h:6,noninfring:[2,6,5,1],entri:[3,6,4],nghttp:4,person:[2,6,5,1],uint32_t:[3,6],self:4,hd_side_request:4,end_push_promis:[3,6],nghttp2_gzip_infl:[3,6],on_frame_send_callback:[3,6],nghttp2_ping:[3,6],input:[2,6,4,5,3],subsequ:[3,6],bin:4,on_begin_headers_callback:[2,6,5,3],format:[2,6,4,5,3],http_parser:5,bit:[3,6,1],strstr:2,signal:[2,6,5,3],lib_error:[3,6],api:[0,6,3],some:[2,6,5,3],back:[3,6],sampl:4,sizeof:[2,5],libssl:4,lev_opt_reus:2,though:4,per:[3,6],larg:[3,6],make_nv2:5,machin:4,run:[2,6,4,5,3],step:[3,6],handshake_readcb:2,idl:[3,6],block:[2,6,4,5,3],nghttp2_err_paus:[3,6],nsm:6,within:4,nghttp2_send_callback:[3,6,5],nghttp2_opt_set:[3,6],occupi:4,inclus:[3,6],errno:2,bodi:[2,6,5,3],"long":[3,6],nghttp2:[0,1,2,3,4,5,6],includ:[0,1,2,3,4,5,6],forward:4,session_ptr:[3,6],link:[2,4],ni_maxhost:2,nghttp2_session_set_stream_user_data:[2,6,3],line:4,concaten:[3,6],utf:4,caller:[2,6,3],nghttpx:4,clear:[3,6],parser:5,repres:[3,6],"char":[2,6,5,3],incomplet:4,sublen:2,titl:2,invalid:[3,6],transport:5,libtool:4,create_http2_stream_data:[2,5],algorithm:[3,6],nghttp2_submit_request:[3,6,5],namelen:[2,6,5,3],getaddrinfo:2,code:[2,6,4,5,3],queri:5,nghttp2_frame_hd:[3,6],cython:4,privat:2,send:[2,6,4,5,3],http_parser_url:5,lower:[3,6],aris:[2,6,5,1],fatal:[2,6,5,3],sent:[2,6,5,3],nghttp2_submit_p:[3,6],untouch:[3,6],relev:[2,5],tri:[3,6],magic:[2,5],http_parser_parse_url:5,"try":4,freed:4,pleas:[2,6,4,5,3],impli:[2,6,5,1],smaller:4,snprintf:5,"0x1":[3,6],"0x0":[3,6],"0x4":[3,6],download:[0,4],index:4,o_rdonli:2,settings_flow_control_opt:[3,6],access:4,experiment:[0,4],inspect:[3,6],ssl_ctx_set_opt:[2,5],nghttp2_enhance_your_calm:[3,6],len:[2,6,5,3],closur:[3,6,5],nghttp2_rst_stream:[3,6],ubuntu:4,becom:[2,6,1,3],sinc:[2,6,4,5,3],remark:[0,3],larger:[3,6],settings_payloadlen:[3,6],autoreconf:4,jansson:4,greac:[2,5],chang:[2,6,3],output_wouldblock_threshold:2,appli:[3,6],bufferev:[2,5],from:[0,1,2,3,4,5,6],commun:[2,4,5],binascii:4,upgrad:[3,6,4],next:[2,6,4,5,3],findproxyforurl:4,usr:4,nghttp2_nv:[2,6,5,3],jxck:4,goawai:[2,6,4,5,3],deflat:[3,6,4],account:[3,6,4,5],retriev:[2,6,5,3],tunnel:4,nghttp2_settings_id:[3,6],aliv:[2,6,3],sslv23_client_method:5,control:[3,6],process:[2,6,4,5,3],fprintf:[2,5],onlin:[3,4],serial:[2,6,5,3],evdns_base_fre:5,nghttp2_session_want_read:[2,6,5,3],ssl_ctx_use_privatekey_fil:2,evbas:[2,5],instead:[3,6],nullifi:[3,6],npn:[2,6,4,5,3],eventcb:[2,5],nghttp2_compression_error:[3,6],alloc:[2,6,3],bind:[0,4],nvlen:[2,6,5,3],correspond:[2,4],element:[2,6,3],issu:[0,6,3],stream_id:[2,6,4,5,3],nghttp2_connect_error:[3,6],ssize_t:[2,6,5,3],furnish:[2,6,5,1],move:[3,6],max_outlen:[3,6],therefor:[3,6,5],nghttp2_session_send:[2,6,5,3],inlen:[3,6,5],recept:[2,6,5,3],crash:3,greater:[3,6],handl:[2,5],nghttp2_goawai:[3,6],handi:5,automat:[3,6],anyth:5,uf_port:5,mode:4,ssl_filetype_pem:2,chunk:[3,6,5],nghttp2_err_temporal_callback_failur:[2,6,3],"static":[2,6,4,5,3],our:5,patch:[3,1],out:[2,1,3,4,5,6],variabl:4,req:[3,6],categori:[3,6,5],suitabl:[3,6],rel:2,field_data:5,recv_callback:[3,6],insid:4,releas:[0,1,3],could:[2,6,5,3],keep:[2,6,4,5,3],length:[2,6,4,5,3],outsid:[3,4],retain:[3,6],softwar:[2,6,5,1],addrinfo:2,date:4,prioriti:[3,6,5],unknown:[2,6,3],system:[2,5],messag:[3,6,5],attach:[2,5],termin:[2,6,4,5,3],ipv4:4,sa_handl:[2,5],enqueu:5,exactli:[2,4],nghttp2_err_header_comp:[3,6],see:[2,6,4,5,3],structur:[2,6,5,3],charact:[2,6,5,3],nghttp2_session_del:[2,6,5,3],bev:[2,5],ssl_new:[2,5],"function":[0,2,3,4,5,6],bufferevent_get_input:[2,5],corrupt:5,have:[2,6,4,5,3],reserv:[3,6],need:[3,6,4,5],ai_socktyp:2,"0x04":4,"0x05":4,"0x00":[3,6,4],nghttp2_err_flow_control:[3,6],nghttp2_refused_stream:[3,6],evbuffer_pullup:[2,5],which:[2,6,4,5,3],singl:[2,6,4,5,3],opaque_data_len:[3,6],unless:[3,6],bufferevent_openssl_socket_new:[2,5],settings_max_concurrent_stream:[2,6,4,5,3],stream_data:[2,5],deploi:4,"class":4,nghttp2_error_cod:[2,6,5,3],nghttp2_err_stream_id_not_avail:[3,6],url:[2,4],request:[2,6,4,5,3],uri:[4,5],pipe:2,determin:4,nghttp2_pack_settings_payload:[3,6],"0x0d":[3,6],"0x0a":[3,6],ssl_load_error_str:[2,5],text:4,bufferevent_get_output:[2,5],redirect:5,locat:5,should:[2,6,5,3],local:[3,6],meant:5,familiar:4,memcpi:[2,5],nghttp2_session_client_new2:[3,6],settings_initial_window_s:[3,6,4],nghttp2_data:[2,6,3],increas:[3,6,5],portion:[2,6,5,1,3],nghttp2_submit_respons:[2,6,3],enabl:[3,6,4],whether:[2,6,5,1],stuff:[3,6],contain:[2,6,4,5,3],nghttp2_window_upd:[3,6],frame:[2,6,4,5,3],knowledg:4,temporarili:[3,6],statu:[0,6,4,3,2],wire:[2,4,5],nghttp2_settings_entri:[2,6,5,3],state:[2,6,4,3],https_uri:5,nghttp2_initial_connection_window_s:[3,6],kei:[2,6,4,3],supporet:4,entir:[2,6,3],last_stream_id:[3,6,4],addit:[2,6,3],revers:4,nghttp2_proto_version_id:[2,6,5,3],equal:2,etc:[2,4,5],instanc:[3,6],uint16_t:[3,6,5],rfc2616:[3,6],commenc:5,respect:[3,6,5],nghttp2_recv_callback:[3,6],ssl_ctx_set_next_proto_select_cb:[3,6,5],adjsut:4,compon:5,json:4,treat:[2,6,3],immedi:[3,6],nghttp2_hcat_head:[3,6],sock_stream:2,evconnlisten:2,on_header_callback:[2,6,5,3],nghttp2_frame_size_error:[3,6],defin:[2,6,5,1,3],eintr:2,helper:[3,6],on_request_recv:2,libxml2:4,squid:4,select_next_proto_cb:[3,6,5],archiv:[2,5],substanti:[2,6,5,1],incom:[2,6,4,3],let:[2,5],member:[2,6,3],python:[0,4],ifndef:[6,1],dyanmic:4,http:[0,1,2,3,4,5,6],hostnam:4,uf_host:5,dealloc:4,peer_max_concurrent_stream:[3,6],off:5,well:[2,5],app_context:2,inflatehd:4,exampl:[2,6,4,5,3],command:4,error_cod:[2,6,4,5,3],nghttp2_data_sourc:[2,6,3],usual:[3,6],paus:[3,6],less:[3,6],send_callback:[2,6,5,3],half:[3,6],obtain:[2,6,5,1],tcp:[2,5],web:[2,4],cert_fil:2,send_server_connection_head:2,priorit:[3,6],addrlen:2,add:[2,6,3],match:[2,5],gmt:4,know:[3,6],nva:[2,6,5,3],python3:4,resid:[2,5],like:[2,6,4,5,3],success:4,nghttp2_pri_lowest:[3,6],nghttp2_flag_end_head:[3,6],necessari:2,tlen:[3,6],page:[2,5],file_read_callback:2,nghttp2_session_client_new:[3,6,5],"export":2,nghttp2_session_get_effective_recv_data_length:[3,6],error_html:2,librari:[0,1,2,3,4,5,6],lead:[3,6],avoid:[2,6,5,3],octet:[2,5],overlap:[3,6],isxdigit:2,outgo:[2,6,3],nghttp2_session_upgrad:[3,6],delete_http2_stream_data:[2,5],"enum":[0,6,3],usag:[2,6,4,5,3],host:[0,4,5,2],nghttp2_nv_compare_nam:[3,6],about:[2,6,5,3],actual:[2,6,5,3],socket:[2,4,5],nghttp2_gzip:[3,6],chrome:4,fals:4,ssl_tlsext_err_ok:[2,6,5,3],disabl:[3,6,4],own:[3,6],nghttp2_err_invalid_fram:[3,6],ssl_op_no_sslv2:[2,5],warranti:[2,6,5,1],automak:4,merg:[2,6,5,1],val:[2,5],ai_famili:2,transfer:[0,6,4,3],intention:[3,6],much:2,buz:4,unexpect:[3,6],bufferevent_fre:[2,5],overflow:[3,6],highest:[3,6],buf:[2,6,3],count:[3,6],succe:[3,6],nghttp2_stream_clos:[3,6],nghttp2_info:[3,6],googlecod:[3,6],displai:4,asynchron:[3,6],limit:[2,6,5,1],otherwis:[2,1,3,4,5,6],problem:[3,6],sockaddr:2,nghttp2_on_frame_not_send_callback:[3,6],strndup:5,"int":[2,6,5,3],nghttp2_flag_end_stream:[2,6,3],allow:[3,6,4],percent:2,detail:[3,6],other:[2,6,5,1,3],nghttp2_err_invalid_argu:[3,6],rememb:[2,5],outlen_ptr:[3,6],stat:2,err_error_str:[2,5],nghttp2_opt_peer_max_concurrent_stream:[3,6],rel_path:2,proto_str:[3,6],debian:4,session_data:[2,5],sphinx:4,eof:[2,6,3],reliabl:[3,6],indirectli:3,rule:[3,6],nghttp2_no_error:[3,6,5]},objtypes:{"0":"c:member","1":"c:macro","2":"c:type","3":"c:function"},titles:["nghttp2 - HTTP/2.0 C Library","nghttp2ver.h","Tutorial: HTTP/2.0 server","API Reference","nghttp2 - HTTP/2.0 C Library","Tutorial: HTTP/2.0 client","nghttp2.h"],objnames:{"0":["c","member","C member"],"1":["c","macro","C macro"],"2":["c","type","C type"],"3":["c","function","C function"]},filenames:["index","nghttp2ver.h","tutorial-server","apiref","package_README","tutorial-client","nghttp2.h"]}) \ No newline at end of file +Search.setIndex({objects:{"":{NGHTTP2_ERR_INVALID_STATE:[3,1,1,""],NGHTTP2_ERR_HEADER_COMP:[3,1,1,""],NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:[3,1,1,""],nghttp2_settings_entry:[3,2,1,""],NGHTTP2_INTERNAL_ERROR:[3,1,1,""],NGHTTP2_PRI_LOWEST:[3,1,1,""],nghttp2_on_frame_recv_callback:[3,2,1,""],NGHTTP2_CLIENT_CONNECTION_HEADER_LEN:[3,1,1,""],nghttp2_goaway:[3,2,1,""],nghttp2_ping:[3,2,1,""],NGHTTP2_ERR_INVALID_FRAME:[3,1,1,""],nghttp2_frame_type:[3,2,1,""],NGHTTP2_ERR_INVALID_STREAM_ID:[3,1,1,""],nghttp2_select_next_protocol:[3,3,1,""],NGHTTP2_ERR_INVALID_HEADER_BLOCK:[3,1,1,""],nghttp2_session_callbacks:[3,2,1,""],NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS:[3,1,1,""],NGHTTP2_ERR_PROTO:[3,1,1,""],NGHTTP2_MAX_HEADER_TABLE_SIZE:[3,1,1,""],nghttp2_submit_window_update:[3,3,1,""],NGHTTP2_ERR_UNSUPPORTED_VERSION:[3,1,1,""],NGHTTP2_SETTINGS_ENABLE_PUSH:[3,1,1,""],nghttp2_window_update:[3,2,1,""],nghttp2_session_client_new2:[3,3,1,""],NGHTTP2_DATA:[3,1,1,""],nghttp2_frame_hd:[3,2,1,""],NGHTTP2_ERR_INVALID_STREAM_STATE:[3,1,1,""],nghttp2_on_header_callback:[3,2,1,""],NGHTTP2_FLAG_ACK:[3,1,1,""],NGHTTP2_STREAM_CLOSED:[3,1,1,""],NGHTTP2_SETTINGS_MAX:[3,1,1,""],NGHTTP2_MAX_WINDOW_SIZE:[3,1,1,""],nghttp2_headers_category:[3,2,1,""],nghttp2_error_code:[3,2,1,""],NGHTTP2_REFUSED_STREAM:[3,1,1,""],nghttp2_on_data_chunk_recv_callback:[3,2,1,""],NGHTTP2_ERR_START_STREAM_NOT_ALLOWED:[3,1,1,""],NGHTTP2_ERR_FLOW_CONTROL:[3,1,1,""],nghttp2_strerror:[3,3,1,""],nghttp2_gzip_inflate_del:[3,3,1,""],NGHTTP2_ERR_FATAL:[3,1,1,""],nghttp2_submit_goaway:[3,3,1,""],nghttp2_error:[3,2,1,""],NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE:[3,1,1,""],NGHTTP2_ERR_NOMEM:[3,1,1,""],NGHTTP2_ERR_PAUSE:[3,1,1,""],NGHTTP2_ENHANCE_YOUR_CALM:[3,1,1,""],NGHTTP2_NO_ERROR:[3,1,1,""],NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS:[3,1,1,""],nghttp2_session_server_new2:[3,3,1,""],NGHTTP2_ERR_DEFERRED:[3,1,1,""],nghttp2_push_promise:[3,2,1,""],NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE:[3,1,1,""],nghttp2_session_get_outbound_queue_size:[3,3,1,""],nghttp2_rst_stream:[3,2,1,""],NGHTTP2_PROTO_VERSION_ID_LEN:[3,1,1,""],NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS:[3,1,1,""],nghttp2_data_source_read_callback:[3,2,1,""],NGHTTP2_SETTINGS_TIMEOUT:[3,1,1,""],NGHTTP2_ERR_WOULDBLOCK:[3,1,1,""],nghttp2_session_resume_data:[3,3,1,""],NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:[3,1,1,""],NGHTTP2_PRI_DEFAULT:[3,1,1,""],nghttp2_session_server_new:[3,3,1,""],NGHTTP2_CONTINUATION:[3,1,1,""],NGHTTP2_FLAG_END_PUSH_PROMISE:[3,1,1,""],NGHTTP2_ERR_INVALID_ARGUMENT:[3,1,1,""],NGHTTP2_ERR_FRAME_SIZE_ERROR:[3,1,1,""],nghttp2_session_del:[3,3,1,""],nghttp2_session_mem_recv:[3,3,1,""],nghttp2_flag:[3,2,1,""],NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE:[3,1,1,""],NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:[3,1,1,""],NGHTTP2_HCAT_REQUEST:[3,1,1,""],NGHTTP2_FLAG_END_HEADERS:[3,1,1,""],nghttp2_gzip:[3,2,1,""],NGHTTP2_RST_STREAM:[3,1,1,""],NGHTTP2_ERR_EOF:[3,1,1,""],NGHTTP2_HCAT_HEADERS:[3,1,1,""],NGHTTP2_VERSION_NUM:[3,1,1,""],NGHTTP2_SETTINGS:[3,1,1,""],nghttp2_frame:[3,2,1,""],nghttp2_submit_push_promise:[3,3,1,""],NGHTTP2_ERR_DEFERRED_DATA_EXIST:[3,1,1,""],NGHTTP2_CANCEL:[3,1,1,""],nghttp2_send_callback:[3,2,1,""],nghttp2_on_frame_send_callback:[3,2,1,""],NGHTTP2_HEADERS:[3,1,1,""],NGHTTP2_VERSION:[3,1,1,""],nghttp2_opt_set:[3,2,1,""],nghttp2_session:[3,2,1,""],NGHTTP2_COMPRESSION_ERROR:[3,1,1,""],NGHTTP2_HCAT_PUSH_RESPONSE:[3,1,1,""],nghttp2_submit_rst_stream:[3,3,1,""],nghttp2_submit_headers:[3,3,1,""],nghttp2_recv_callback:[3,2,1,""],nghttp2_session_get_stream_user_data:[3,3,1,""],NGHTTP2_FLAG_PRIORITY:[3,1,1,""],nghttp2_nv:[3,2,1,""],nghttp2_on_invalid_frame_recv_callback:[3,2,1,""],nghttp2_version:[3,3,1,""],nghttp2_on_unknown_frame_recv_callback:[3,2,1,""],NGHTTP2_ERR_STREAM_CLOSED:[3,1,1,""],nghttp2_opt:[3,2,1,""],NGHTTP2_ERR_CALLBACK_FAILURE:[3,1,1,""],NGHTTP2_ERR_GOAWAY_ALREADY_SENT:[3,1,1,""],NGHTTP2_FLOW_CONTROL_ERROR:[3,1,1,""],nghttp2_session_set_stream_user_data:[3,3,1,""],nghttp2_check_header_value:[3,3,1,""],NGHTTP2_ERR_STREAM_CLOSING:[3,1,1,""],nghttp2_session_client_new:[3,3,1,""],nghttp2_check_header_name:[3,3,1,""],nghttp2_info:[3,2,1,""],NGHTTP2_PROTO_VERSION_ID:[3,1,1,""],nghttp2_settings_id:[3,2,1,""],nghttp2_session_send:[3,3,1,""],NGHTTP2_PROTOCOL_ERROR:[3,1,1,""],nghttp2_gzip_inflate:[3,3,1,""],nghttp2_session_upgrade:[3,3,1,""],nghttp2_on_begin_headers_callback:[3,2,1,""],NGHTTP2_ERR_INSUFF_BUFSIZE:[3,1,1,""],nghttp2_settings:[3,2,1,""],nghttp2_on_frame_not_send_callback:[3,2,1,""],nghttp2_session_get_effective_recv_data_length:[3,3,1,""],nghttp2_submit_data:[3,3,1,""],nghttp2_submit_response:[3,3,1,""],NGHTTP2_CLIENT_CONNECTION_HEADER:[3,1,1,""],NGHTTP2_FLAG_NONE:[3,1,1,""],nghttp2_session_terminate_session:[3,3,1,""],nghttp2_submit_settings:[3,3,1,""],NGHTTP2_HCAT_RESPONSE:[3,1,1,""],NGHTTP2_PING:[3,1,1,""],NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE:[3,1,1,""],nghttp2_priority:[3,2,1,""],nghttp2_session_want_read:[3,3,1,""],NGHTTP2_VERSION_AGE:[3,1,1,""],NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE:[3,1,1,""],NGHTTP2_CONNECT_ERROR:[3,1,1,""],NGHTTP2_FLAG_END_STREAM:[3,1,1,""],nghttp2_on_stream_close_callback:[3,2,1,""],NGHTTP2_PUSH_PROMISE:[3,1,1,""],nghttp2_data_provider:[3,2,1,""],NGHTTP2_ERR_PUSH_DISABLED:[3,1,1,""],nghttp2_session_recv:[3,3,1,""],nghttp2_session_get_effective_local_window_size:[3,3,1,""],NGHTTP2_INITIAL_WINDOW_SIZE:[3,1,1,""],NGHTTP2_WINDOW_UPDATE:[3,1,1,""],NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS:[3,1,1,""],nghttp2_session_want_write:[3,3,1,""],nghttp2_submit_priority:[3,3,1,""],nghttp2_session_get_stream_effective_local_window_size:[3,3,1,""],nghttp2_headers:[3,2,1,""],nghttp2_before_frame_send_callback:[3,2,1,""],NGHTTP2_GOAWAY:[3,1,1,""],NGHTTP2_ERR_GZIP:[3,1,1,""],nghttp2_is_fatal:[3,3,1,""],nghttp2_submit_ping:[3,3,1,""],NGHTTP2_FRAME_SIZE_ERROR:[3,1,1,""],nghttp2_data_source:[3,2,1,""],NGHTTP2_ERR_STREAM_SHUT_WR:[3,1,1,""],NGHTTP2_PRIORITY:[3,1,1,""],nghttp2_submit_request:[3,3,1,""],nghttp2_session_get_stream_effective_recv_data_length:[3,3,1,""],nghttp2_pack_settings_payload:[3,3,1,""],nghttp2_data:[3,2,1,""],nghttp2_gzip_inflate_new:[3,3,1,""],nghttp2_nv_compare_name:[3,3,1,""]},nghttp2_session_callbacks:{on_invalid_frame_recv_callback:[3,0,1,""],before_frame_send_callback:[3,0,1,""],on_stream_close_callback:[3,0,1,""],on_data_chunk_recv_callback:[3,0,1,""],on_begin_headers_callback:[3,0,1,""],send_callback:[3,0,1,""],on_unknown_frame_recv_callback:[3,0,1,""],on_frame_recv_callback:[3,0,1,""],on_header_callback:[3,0,1,""],on_frame_not_send_callback:[3,0,1,""],on_frame_send_callback:[3,0,1,""],recv_callback:[3,0,1,""]},nghttp2_frame:{push_promise:[3,0,1,""],settings:[3,0,1,""],ping:[3,0,1,""],rst_stream:[3,0,1,""],priority:[3,0,1,""],headers:[3,0,1,""],goaway:[3,0,1,""],window_update:[3,0,1,""],data:[3,0,1,""],hd:[3,0,1,""]},nghttp2_ping:{hd:[3,0,1,""]},nghttp2_data_provider:{source:[3,0,1,""],read_callback:[3,0,1,""]},nghttp2_priority:{pri:[3,0,1,""],hd:[3,0,1,""]},nghttp2_settings_entry:{settings_id:[3,0,1,""],value:[3,0,1,""]},nghttp2_window_update:{hd:[3,0,1,""],window_size_increment:[3,0,1,""]},nghttp2_frame_hd:{stream_id:[3,0,1,""],length:[3,0,1,""],flags:[3,0,1,""],type:[3,0,1,""]},nghttp2_info:{age:[3,0,1,""],version_str:[3,0,1,""],version_num:[3,0,1,""],proto_str:[3,0,1,""]},nghttp2_rst_stream:{error_code:[3,0,1,""],hd:[3,0,1,""]},nghttp2_nv:{valuelen:[3,0,1,""],namelen:[3,0,1,""],name:[3,0,1,""],value:[3,0,1,""]},nghttp2_headers:{nvlen:[3,0,1,""],pri:[3,0,1,""],hd:[3,0,1,""],nva:[3,0,1,""],cat:[3,0,1,""]},nghttp2_opt_set:{no_auto_stream_window_update:[3,0,1,""],peer_max_concurrent_streams:[3,0,1,""],no_auto_connection_window_update:[3,0,1,""]},nghttp2_goaway:{opaque_data:[3,0,1,""],error_code:[3,0,1,""],opaque_data_len:[3,0,1,""],hd:[3,0,1,""],last_stream_id:[3,0,1,""]},nghttp2_data_source:{fd:[3,0,1,""],ptr:[3,0,1,""]},nghttp2_push_promise:{promised_stream_id:[3,0,1,""],nvlen:[3,0,1,""],nva:[3,0,1,""],hd:[3,0,1,""]},nghttp2_settings:{niv:[3,0,1,""],hd:[3,0,1,""],iv:[3,0,1,""]}},terms:{my_obj:[3,6],nghttp2_io_flag:6,nghttp2_cancel:[3,6],opt_set:[3,6],prefix:[2,6,3],nghttp2_session_get_stream_effective_local_window_s:[3,6],"const":[2,6,5,3],nghttp2_submit_:[2,5],under:[3,6,4],bufferevent_getfd:5,spec:[3,6],merchant:[2,6,5,1],digit:5,"void":[2,6,5,3],bufferevent_ssl:[2,5],initialize_nghttp2_setup:[2,5],verif:5,nghttp2_settings_initial_window_s:[3,6],warnx:[2,5],on_stream_close_callback:[2,6,5,3],direct:4,ssl_op_no_session_resumption_on_renegoti:[2,5],neg:[3,6],nghttp2_err_insuff_bufs:[3,6],"new":[2,6,4,5,3],tatsuhiro:[0,1,2,4,5,6],nghttp2_session_resume_data:[3,6],ipproto_tcp:[2,5],abov:[2,1,3,4,5,6],initialize_app_context:2,here:[2,6,4,5,3],met:[2,6,5,3],path:[2,4,5],settings_timeout:[3,6],interpret:[3,6],nextprotoneg:[3,6],sslv23_server_method:2,permit:[2,6,5,1],nghttp2_submit_prior:[3,6],aka:[3,6,4],nghttp2_err_gzip:[3,6],nghttp2_frame:[2,6,5,3],bufferevent_ssl_connect:5,substr:2,bev_event_error:[2,5],bufferevent_socket_connect_hostnam:5,unit:4,describ:[2,6,5,3],would:[3,6],call:[2,6,4,5,3],asset:4,nghttp2_on_invalid_frame_recv_callback:[3,6],nghttp2_version:[3,6,1],type:[0,2,3,4,5,6],tell:[2,6,5,3],relat:[2,5],notic:[2,6,5,1],warn:2,ssl_shutdown:[2,5],herebi:[2,6,5,1],unpack:[3,6],must:[2,6,4,5,3],word:[3,6],err:[2,5],exit_failur:[2,5],setup:[2,5],work:[2,4],lev_opt_close_on_fre:2,nghttp2_flag_ack:[3,6],root:[2,4],syn_repli:[3,6],defer:[2,6,5,3],give:[3,6],indic:[2,6,4,5,3],want:[2,6,5,3],unsign:[2,6,5,3],nghttp2_settings_flow_control_opt:[3,6],end:[2,6,5,3],datalen:[2,5],how:5,nghttp2_err_fat:[3,6],nghttp2_frame_typ:[3,6],updat:[3,6],nghttp2_msg_more:6,after:[2,6,4,5,3],badli:[3,6],demonstr:5,request_path:2,attempt:[3,6],third:[2,6,5,3],opaqu:[3,6],exclud:[3,6],receiv:[2,6,5,3],first:[2,6,4,5,3],order:[2,6,4,3],frontend:4,over:[2,4,5],becaus:[2,6,5,3],eagain:[2,5],vari:4,fit:[2,6,5,1],fwrite:5,deflate_s:4,hidden:[3,6],them:[2,6,5,3],thei:[2,6,4,5,3],safe:[2,6,3],"break":[2,6,5,3],promis:[3,6],choic:[3,6],ai_addr:2,timeout:[2,5],each:[2,6,4,5,3],debug:[3,6,5],side:[2,6,3],mean:[3,6,4,5],slen:2,protocol_error:[3,6],http2_stream_data:[2,5],nghttp2_session_server_new2:[3,6],network:[2,5],content:[0,4,2],end_stream:[3,6,4],situat:[2,5],free:[2,6,5,1,3],spdy:[3,6,4],openssl:[2,4,5],nghttp2_version_num:[3,6,1],sigact:[2,5],rang:[3,6,4],restrict:[2,6,5,1],nghttp2_protocol_error:[3,6],alreadi:[2,6,5,3],opaque_data:[3,6,4],payload:[3,6],nghttp2_max_header_table_s:[3,6],too:[2,6,3],memcmp:2,sigpip:[2,5],listen:[2,4],tool:[0,6,4,3],travers:2,compressor:4,target:[3,6,4],provid:[2,1,3,4,5,6],project:[0,4],matter:[3,6],nghttp2_continu:[3,6],increment:[3,6],nghttp2_session_recv:[3,6],nghttp2_session_get_stream_effective_recv_data_length:[3,6],transmit:[3,6,5],sig_ign:[2,5],shall:[2,6,5,1],object:[2,6,4,5,3],writecb:[2,5],nghttp2_settings_timeout:[3,6],simplic:5,don:[2,6,3],hex_to_uint:2,doc:4,flow:[3,6],doe:[2,6,4,5,3],nghttp2_gzip_inflate_new:[3,6],sum:4,on_invalid_frame_recv_callback:[3,6],bev_event_eof:[2,5],pkg:4,identifi:[2,6,5,3],bufferevent_setcb:[2,5],involv:[3,6],explain:5,configur:[3,6,4],apach:4,nghttp2_err_invalid_stream_id:[3,6],busi:[2,5],oct:4,nghttp2_err_proto:[3,6],authoritylen:5,stop:[2,5],end_head:[3,6,4],evbuffer_drain:[2,5],nghttp2_no_error:[3,6,5],bar:4,ai_pass:2,ietf:[0,6,4,3],baz:4,push_promis:[2,6,3],method:[2,6,4,5,3],nghttp2_strerror:[2,6,5,3],nghttp2_gzip_inflate_del:[3,6],bufferevent_ssl_accept:2,nul:[3,6],result:[2,6,5,3],respons:[2,6,4,5,3],fail:[3,6],key_fil:2,subject:[2,6,5,1],said:[3,6],figur:4,bev_opt_close_on_fre:[2,5],accord:[3,6],extens:[4,5],advertis:[2,5],setsockopt:[2,5],against:[3,6],ssl_ctx_use_certificate_chain_fil:2,header_t:4,logic:2,browser:4,com:[0,6,4,3],int32_t:[2,6,5,3],assum:[3,6],duplic:[3,6],reciev:5,liabil:[2,6,5,1],evbuffer_get_length:[2,5],union:[0,6,3,2],max_deflate_s:4,been:[2,6,5,3],trigger:[3,6],interest:[2,4,5],basic:4,tini:5,life:2,regul:[2,5],ani:[2,1,3,4,5,6],ewouldblock:[2,5],ssl_op_no_compress:[2,5],servic:2,properti:[2,5],nghttp2_on_begin_headers_callback:[3,6,5],bev_event_timeout:[2,5],printabl:5,nghttp2_set:[3,6],promised_stream_id:[3,6],conf:4,sever:[2,6,4,5,3],perform:[2,6,4,3],make:[2,6,4,3],transpar:[3,6],headlen:[3,6],split:[3,6],version_str:[3,6],nghttp2_on_stream_close_callback:[3,6,5],complet:[2,6,5,3],start_listen:2,bufferevent_openssl_get_ssl:[2,5],nghttp2_err_deferred_data_exist:[3,6],ssl_ctx_new:[2,5],zlib1g:4,ownership:[3,6],niv:[3,6,4],thu:[2,6,3],nghttp2_session_get_effective_local_window_s:[3,6],client:[0,2,3,4,5,6],thi:[0,1,2,3,4,5,6],endif:[2,6,1],gzip:[3,6,4],left:[3,6],protocol:[0,2,3,4,5,6],just:[2,6,4,5,3],"0x01":4,initiate_connect:5,ifdef:[2,6],previous:[3,6],easi:4,els:[2,5],applic:[2,6,4,5,3],initialize_nghttp2_sess:[2,5],specif:[2,6,5,3],arbitrari:[3,6],http2_session_data:[2,5],client_addr:2,manual:4,html:[0,6,4,3,2],tcp_nodelai:[2,5],unnecessari:5,underli:[2,5],www:[3,6],right:[2,6,5,1],deal:[2,6,5,1,3],intern:[3,6],successfulli:[2,6,5,3],transmiss:[2,6,5,3],ni_numerichost:2,bottom:[3,6],nghttp2_data_source_read_callback:[3,6],track:[2,4,5],condit:[2,6,5,1,3],foo:4,localhost:4,sensibl:[3,6],repositori:[2,5],peer:[2,6,5,3],post:[3,6,4],decompressor:4,inlen_ptr:[3,6],nghttp2_submit_data:[3,6],nghttp2_settings_max_concurrent_stream:[2,6,5,3],produc:[3,6],evbuff:[2,5],encod:[2,6,4,3],down:[2,5],pair:[2,6,4,5,3],errx:[2,5],git:[0,6,4,3],session_send:[2,5],wai:[3,6,4],support:[2,6,4,5,3],verbos:4,overhead:4,lowest:[3,6],head:[2,6,3],event_bas:[2,5],offer:4,taken:[3,6],"true":4,reset:5,ssl_ctx_free:[2,5],maximum:[3,6,4],until:[3,6],deafult:4,autoconf:4,emit:[2,6,5,3],nghttp2_initial_window_s:[3,6],featur:4,httpbi:[0,6,4,3],netdb:2,unreleas:4,exist:[3,6,4],ai_flag:2,ends_with:2,check:[2,6,5,3],delete_http2_session_data:[2,5],when:[2,6,4,5,3],role:[2,6,5,3],test:[0,4],send_client_connection_head:5,unlimit:[3,6],intend:2,af_unspec:[2,5],nghttp2_max_window_s:[3,6],technot:[3,6],max_siz:4,evconnlistener_new_bind:2,longer:[2,4],nghttp2_check_header_nam:[3,6],print_head:5,time:[2,6,4,3],push:[3,6,4],skip:[3,6],evbuffer_remov:2,nghttp2_on_frame_recv_callback:[3,6,5],nghttp2ver_h:1,decid:[3,6],create_ssl_ctx:[2,5],depend:[2,5],readabl:5,sourc:[0,6,5,3,2],string:[2,6,4,5,3],nghttp2_settings_enable_push:[3,6],level:[2,6,3],did:[3,6,5],item:4,settings_id:[3,6],conhead:2,upper:[3,6],sign:4,port:[2,4,5],appear:[3,6,4],event_base_fre:[2,5],current:[2,6,4,3],gener:[3,6,4],address:4,nghttp2_submit_rst_stream:[2,6,3],connect_error:[3,6],queue:[2,6,5,3],behav:[3,6],ourselv:[2,5],nghttp2_err_goaway_already_s:[3,6],regardless:[3,6],extra:[4,5],modul:4,prefer:[3,6],instal:4,hdinflat:4,memori:[2,6,4,5,3],strdup:2,prev:2,reorder:[3,6,5],rst_stream:[2,6,5,3],ctype:2,nghttp2_submit_window_upd:[3,6],prepar:[3,6],stream_user_data:[3,6,5],cat:[2,6,5,3],descriptor:[2,6,3],can:[2,6,4,5,3],http2:[0,6,4,3],purpos:[2,6,5,1],uf_path:5,claim:[2,6,5,1],stream:[2,6,4,5,3],agent:4,critic:[3,6],abort:[3,6],nghttp2_header:[2,6,5,3],occur:[3,6],alwai:[2,6,3],multipl:[2,6,5,3],charset:4,ping:[3,6],write:[2,4,5],opt_set_mask:[3,6],max:5,intrus:2,mai:[2,6,4,5,3],acceptcb:2,data:[2,6,4,5,3],autotool:4,stdin:4,inform:[2,6,4,5,3],"switch":[2,4,5],aaaabaaaagqaaaahaad__w:4,talk:[2,4],nghttp2_err_stream_shut_wr:[3,6],size_t:[2,6,5,3],nghttp2_err_unsupported_vers:[3,6],still:[2,6,4,3],pointer:[2,6,3],entiti:2,disconnect:[2,5],precondit:[3,6],tort:[2,6,5,1],window:[3,6],main:[2,5],non:[2,6,4,5,3],recal:5,initi:[2,6,5,3],nghttp2_submit_head:[3,6],nghttp2_on_header_callback:[2,6,5,3],"0x000400":1,name:[2,6,4,5,3],version_num:[3,6],config:4,no_error:4,drop:[2,6,5,3],replac:[3,6],individu:[3,6],continu:[2,6,4,5,3],event_base_loop:[2,5],turoti:5,happen:[2,4,5],ai_addrlen:2,space:[3,6,4],output_length:4,nghttp2_flag_end_push_promis:[3,6],earlier:[2,4,5],event_base_new:[2,5],argv:[2,5],org:[0,6,4,3],"byte":[2,6,4,5,3],argc:[2,5],care:[3,6],nghttp2_opt_no_auto_connection_window_upd:[3,6],nghttp2ver:[0,6,1,3],"88448504252dd5918485":4,befor:[2,6,4,5,3],thing:[2,6,5,3],nghttp2_flag_non:[2,6,5,3],place:[3,6],evdns_base_new:5,oper:[3,6,4],directli:[2,6,5,3],onc:[3,6],arrai:[3,6,4,5],yourself:4,nghttp2_is_fat:[3,6],nghttp2_flow_control_error:[3,6],submit:[3,6,5],on_frame_recv_callback:[2,6,5,3],open:[2,6,4,3],size:[2,6,4,3],avail:[2,6,4,5,3],given:[3,6],necessarili:[3,6],draft:[0,6,4,3],internal_error:[3,6],conveni:[3,6],ssl_ctx:[2,6,5,3],copi:[2,6,5,1,3],specifi:[2,6,4,5,3],"short":[2,5],holder:[2,6,5,1],than:[2,6,4,3],serv:2,wide:2,nghttp2_session_get_outbound_queue_s:[3,6],were:[2,5],posit:[3,6],read_callback:[2,6,3],enhance_your_calm:[3,6],fork:4,sai:[3,6],pri:[3,6],argument:[2,6,4,5,3],deliv:[3,6],bitwis:[3,6],form:[3,6],nghttp2_flag_prior:[3,6],destroi:[2,5],payloadlen:[3,6],note:[2,6,4,5,3],take:[2,6,4,5,3],noth:[3,6],begin:5,sure:[2,4,5],normal:[3,6],buffer:[2,6,4,5,3],compress:[0,4],nghttp2_hcat_request:[2,6,5,3],pathlen:5,sublicens:[2,6,5,1],nghttp2_before_frame_send_callback:[3,6,5],http2_select:[3,6],later:[2,6,5,3],gracefulli:5,show:[4,5],unprocess:[2,5],concurr:[2,6,3],permiss:[2,6,5,1],threshold:2,onli:[2,6,4,5,3],state:[2,6,4,3],"4e5535a027780":4,overwritten:[3,6],hddeflat:4,variou:[3,6],get:[2,6,4,5,3],outlen:[3,6,5],ssl:[2,6,4,5,3],cannot:[2,6,3],nghttpd:4,requir:[0,6,4,3],nghttp2_set_stream_user_data:2,multi:4,aris:[2,6,5,1],reserv:[3,6],detect:[3,6,4],"import":4,fcntl:2,pipefd:2,evdns_bas:5,style:4,submit_request:5,region:[3,6],contract:[2,6,5,1],tutori:[0,5,2],deflatehd:4,mani:[3,6],nghttp2_data_provid:[2,6,3],unistd:[2,5],nghttp2_err_too_many_inflight_set:[3,6],cancel:[3,6],damag:[2,6,5,1],header_table_s:4,nghttp2_settings_max:[3,6],"abstract":[2,5],nghttp2_on_unknown_frame_recv_callback:[3,6],nghttp2_opt:[3,6],those:[2,6,5,3],uf_queri:5,hdr:[2,4,5],invok:[2,6,5,3],invoc:[2,6,3],on_data_chunk_recv_callback:[3,6,5],stdout:[4,5],ascii:[3,6],develop:[0,4],author:[2,6,4,5,1],bev_opt_defer_callback:[2,5],alphabet:[3,6],same:[2,6,4,5,3],ssl_library_init:[2,5],binari:5,pac:4,document:[0,1,2,4,5,6],finish:[2,5],decompress:[3,6,4],handshake_leftlen:2,extern:6,postpon:[3,6],macro:[0,6,1,3],without:[2,1,3,4,5,6],nghttp2_push_promis:[3,6],event2:[2,5],nghttp2_err_def:[3,6],nghttp2_submit_set:[2,6,5,3],execut:4,multiplex:[2,4],struct:[0,6,5,3,2],hint:2,except:[3,6],identif:[3,6],nghttp2_select_next_protocol:[3,6,5],real:5,create_http2_session_data:[2,5],nghttp2_version_ag:[3,6],nghttp2_check_header_valu:[3,6],next_proto_cb:2,integ:[3,6],server:[0,2,3,4,5,6],either:[2,6,3],output:[2,6,4,5,3],manag:[2,6,3],stream_clos:[3,6],ssl_ctx_set_next_protos_advertised_cb:2,handshak:[2,5],nonzero:[2,6,3],easili:5,exit:[2,5],freed:4,base64url:[3,6],inspect:[3,6],found:[2,6,3],getnameinfo:2,src:4,inflater_ptr:[3,6],ack:[3,6,4],dnsbase:5,settings_payload:[3,6],act:[2,5],routin:[2,5],no_auto_stream_window_upd:[3,6],least_vers:[3,6],error_repli:2,adjsut:4,b2a_hex:4,nghttp2_hcat_respons:[3,6,5],hex:[2,4],start:[2,6,4,5,3],nghttp2_err_stream_clos:[3,6],low:[3,6],lot:[3,6],ipv6:4,strictli:[3,6],next_proto_list:2,nghttp2_proto_version_id_len:[2,6,3],nghttp2_err_invalid_st:[3,6],possibl:[2,6,5,3],"default":[2,6,4,3],applayerprotoneg:[3,6],hpack:[0,4],err_get_error:[2,5],expect:4,creat:[2,6,4,5,3],mainli:[3,6],decreas:[3,6],file:[2,1,3,4,5,6],nghttp2_err_invalid_header_block:[3,6],fill:2,denot:[3,6,5],functypedef:6,googl:4,field:[2,6,4,5,3],valid:[3,6,4],nghttp2_prioriti:[3,6],ignor:[2,6,3],you:[2,6,4,5,3],sequenc:[2,6,4,5,3],reduc:[3,6],cunit:4,directori:[2,4,5],mask:[3,6],represent:[3,1],all:[2,6,5,1,3],on_unknown_frame_recv_callback:[3,6],illustr:4,nghttp2_err_start_stream_not_allow:[3,6],lack:[3,6],follow:[2,1,3,4,5,6],ptr:[2,6,5,3],app_cont:2,uint8_t:[2,6,5,3],readcb:[2,5],program:[0,4,5,2],bufferevent_writ:[2,5],"case":[2,6,4,5,3],far:[2,5],settings_header_table_s:[3,6,4],print:[4,5],failur:[3,6],veri:[3,6,5],no_auto_connection_window_upd:[3,6],"__cplusplu":6,list:[2,6,3],nghttp2_headers_categori:[3,6],adjust:[3,6],stderr:[2,4,5],small:[3,6],session_recv:2,zero:[3,6],pass:[3,6,5],further:[2,6,5,3],what:[3,6,4],sub:2,sun:4,section:[3,6],delet:5,version:[0,6,4,1,3],"public":[0,6,4,3],libjansson:4,percentage_of_original_s:4,excess:2,modifi:[2,6,4,5,1],valu:[2,6,4,5,3],search:2,ai_addrconfig:2,nghttp2_err_push_dis:[3,6],prior:4,amount:[2,5],action:[2,6,5,1,3],via:[2,6,4,5,3],primit:5,famili:[2,5],establish:[2,5],select:[3,6,4,5],regist:2,libev:[0,4,5,2],bev_event_connect:[2,5],minor:[3,1],more:[2,6,4,5,3],tsujikawa:[2,6,5,1],nghttp2_settings_header_table_s:[3,6],nghttp2_pri_default:[3,6,5],flag:[2,6,4,5,3],particular:[2,6,5,1,3],known:[3,6],nghttp2_err_wouldblock:[2,6,5,3],endpoint:[3,6,4],dev:[4,1],remain:[2,6,5,3],share:[3,6,4],accept:[2,6,4,3],minimum:2,ssl_op_al:[2,5],create_ssl:[2,5],strlen:[2,5],huge:[2,5],netinet:[2,5],secur:4,anoth:[3,6],serveraddr:4,reject:[3,6],sec9:[3,6],simpl:[2,6,5,3],resourc:[0,6,4,5,3],referenc:4,variant:[3,6],spdylai:4,associ:[2,1,3,4,5,6],github:[0,4],caus:[3,6],callback:[2,6,5,3],alpn:[3,6,4],authroiti:5,hypertext:[0,4],libcunit1:4,through:[2,4],paramet:[3,6,5],typedef:[0,6,5,3,2],nghttp2_hcat_push_respons:[3,6],pend:[2,6,5,3],nghttp2_err_eof:[3,6],progoram:5,valuelen:[2,6,5,3],tri:[3,6],"return":[2,6,4,5,3],check_path:2,synopsi:[2,5],nghttp2_initial_max_concurrent_stream:[3,6],readlen:2,nghttp2_err_callback_failur:[2,6,5,3],tear:[2,5],achiev:[2,6,3],fulli:2,trailer:[3,6],nghttp2_on_frame_send_callback:[3,6],monoton:5,realli:5,connect:[2,1,3,4,5,6],field_set:5,event:[2,6,5,1],app_ctx:2,publish:[2,6,5,1],primari:[3,6],etag:4,nghttp2_client_connection_header_len:[2,6,5,3],on_frame_not_send_callback:[3,6],proxi:[0,4],differ:[3,6],effect:[3,6],reason:[2,6,3],base:[2,4,5],put:[3,6],nghttp2_session_mem_recv:[2,6,5,3],nghttp2_flag:[3,6],recv:4,thread:[2,4],omit:[3,6,5],nghttp2_err_invalid_stream_st:[3,6],assign:[2,6,5,3],feed:[2,5],major:[3,1],notifi:2,prevent:[3,6],number:[2,6,1,3],"0x8":[3,6],done:[2,4,5],construct:[3,6],stdlib:6,nghttp2_internal_error:[2,6,3],script:4,data_prd:[2,6,3],nghttp2_session_get_stream_user_data:[2,6,5,3],least:[3,6,4],scheme:[4,5],store:[2,6,5,3],input_length:4,"0x0":[3,6],option:[2,6,4,5,3],similarli:[3,6],nghttp2_client_connection_head:[2,6,5,3],pars:5,kind:[2,6,5,1,3],doubli:2,remot:[2,6,4,5,3],remov:[2,6,3],bridg:4,ai_next:2,consumpt:[2,5],nghttp2_error:[3,6],window_size_incr:[3,6,4],lib_error_cod:[3,6],arrlen:[2,5],packag:4,"null":[2,6,5,3],syn_stream:[3,6],sell:[2,6,5,1],outbound:[3,6],equival:[3,6],afram:[3,6],also:[2,6,4,5,3],build:[0,4,5],nghttp2_err_frame_size_error:[3,6],make_nv:[2,5],distribut:[2,6,5,1],reacb:5,reach:[3,6],chart:[3,6],most:[3,6],vnu:4,charg:[2,6,5,1],addr:2,"01881f3468e5891afcbf83868a3d856659c62e3f":4,o_rdonli:2,frame_size_error:[3,6,4],session:[2,6,5,3],nghttp2_submit_push_promis:[3,6],copyright:[2,6,5,1],refused_stream:[3,6],nghttp2_opt_no_auto_stream_window_upd:[3,6],queu:[2,6,5,3],express:[2,6,5,1],window_upd:[3,6,4],liabl:[2,6,5,1],before_frame_send_callback:[3,6,5],retreiv:5,crt:2,certif:[2,4,5],set:[2,6,4,5,3],seq:4,sep:4,ousid:4,remove_stream:2,nghttp2_submit_goawai:[3,6],arg:[2,6,5,3],close:[2,6,4,5,3],analog:[3,6],strchr:2,someth:[3,6],won:[2,6,3],hold:[3,6],nghttp2_on_data_chunk_recv_callback:[3,6,5],numer:[3,6,1],percent_decod:2,both:[2,6,4,5,3],last:[3,6,4],delimit:4,nghttp2_session_want_writ:[2,6,5,3],tempor:[3,6],context:[2,6,4,5,3],compression_error:[3,6],whole:[3,6],simpli:[2,5],send_server_connection_head:2,header:[0,2,3,4,5,6],shutdown:[2,6,5,3],nghttp2_session_client_new:[3,6,5],nghttp2_session:[2,6,5,3],backend:4,due:[3,6],empti:[2,6,4,5,3],send_respons:2,whom:[2,6,5,1],stdint:6,add_stream:2,flight:[3,6],nghttp2_err_nomem:[3,6],settings_enable_push:[3,6,4],nghttp2_session_terminate_sess:[3,6,5],buflen:[3,6],func:6,next_proto_list_len:2,look:[2,5],"while":[2,6,5,3],behavior:[3,6],error:[2,6,4,5,3],loop:[2,5],malloc:[2,5],nghttp2_session_callback:[2,6,5,3],readi:2,user_data:[2,6,5,3],itself:[2,6,5,3],flow_control_error:[3,6],grant:[2,6,5,1],belong:[3,6],read:[2,6,4,5,3],decod:[2,6,3],uf_schema:5,mytyp:[3,6],inflat:[3,6,4],alert:4,moment:4,user:[3,6,4,5],implement:[0,2,3,4,5,6],nghttp2_h:6,noninfring:[2,6,5,1],entri:[3,6,4],nghttp:4,person:[2,6,5,1],uint32_t:[3,6],self:4,hd_side_request:4,end_push_promis:[3,6],nghttp2_gzip_infl:[3,6],on_frame_send_callback:[3,6],nghttp2_ping:[3,6],input:[2,6,4,5,3],subsequ:[3,6],bin:4,on_begin_headers_callback:[2,6,5,3],format:[2,6,4,5,3],http_parser:5,bit:[3,6,1],strstr:2,signal:[2,6,5,3],lib_error:[3,6],bufferev:[2,5],some:[2,6,5,3],back:[3,6],sampl:4,sizeof:[2,5],libssl:4,lev_opt_reus:2,though:4,per:[3,6],larg:[3,6],make_nv2:5,machin:4,run:[2,6,4,5,3],step:[3,6],handshake_readcb:2,idl:[3,6],block:[2,6,4,5,3],nghttp2_err_paus:[3,6],nsm:6,within:4,nghttp2_send_callback:[3,6,5],nghttp2_opt_set:[3,6],occupi:4,inclus:[3,6],errno:2,bodi:[2,6,5,3],"long":[3,6],nghttp2:[0,1,2,3,4,5,6],includ:[0,1,2,3,4,5,6],forward:4,session_ptr:[3,6],link:[2,4],ni_maxhost:2,nghttp2_session_set_stream_user_data:[2,6,3],line:4,concaten:[3,6],utf:4,caller:[2,6,3],nghttpx:4,clear:[3,6],parser:5,repres:[3,6],"char":[2,6,5,3],incomplet:4,sublen:2,titl:2,invalid:[3,6],transport:5,libtool:4,create_http2_stream_data:[2,5],algorithm:[3,6],nghttp2_submit_request:[3,6,5],namelen:[2,6,5,3],getaddrinfo:2,code:[2,6,4,5,3],queri:5,nghttp2_frame_hd:[3,6],cython:4,privat:2,send:[2,6,4,5,3],http_parser_url:5,lower:[3,6],sens:[3,6],fatal:[2,6,5,3],sent:[2,6,5,3],nghttp2_submit_p:[3,6],untouch:[3,6],relev:[2,5],"0x010203":[3,1],magic:[2,5],http_parser_parse_url:5,"try":4,refer:[0,6,4,3],pleas:[2,6,4,5,3],impli:[2,6,5,1],smaller:4,snprintf:5,"0x1":[3,6],memset:[2,5],"0x4":[3,6],download:[0,4],index:4,compar:[3,6,5],settings_flow_control_opt:[3,6],access:4,experiment:[0,4],nghttp2_session_server_new:[2,6,3],ssl_ctx_set_opt:[2,5],nghttp2_enhance_your_calm:[3,6],len:[2,6,5,3],closur:[3,6,5],nghttp2_rst_stream:[3,6],ubuntu:4,becom:[2,6,1,3],sinc:[2,6,4,5,3],remark:[0,3],larger:[3,6],host:[0,4,5,2],autoreconf:4,jansson:4,greac:[2,5],chang:[2,6,3],output_wouldblock_threshold:2,appli:[3,6],api:[0,6,3],from:[0,1,2,3,4,5,6],commun:[2,4,5],binascii:4,upgrad:[3,6,4],next:[2,6,4,5,3],findproxyforurl:4,usr:4,nghttp2_nv:[2,6,5,3],jxck:4,goawai:[2,6,4,5,3],deflat:[3,6,4],account:[3,6,4,5],retriev:[2,6,5,3],tunnel:4,nghttp2_settings_id:[3,6],aliv:[2,6,3],sslv23_client_method:5,control:[3,6],process:[2,6,4,5,3],fprintf:[2,5],onlin:[3,4],serial:[2,6,5,3],evdns_base_fre:5,nghttp2_session_want_read:[2,6,5,3],ssl_ctx_use_privatekey_fil:2,evbas:[2,5],instead:[3,6],nullifi:[3,6],npn:[2,6,4,5,3],eventcb:[2,5],nghttp2_compression_error:[3,6],alloc:[2,6,3],bind:[0,4],nvlen:[2,6,5,3],correspond:[2,4],element:[2,6,3],issu:[0,6,3],stream_id:[2,6,4,5,3],nghttp2_connect_error:[3,6],ssize_t:[2,6,5,3],furnish:[2,6,5,1],move:[3,6],max_outlen:[3,6],therefor:[3,6,5],nghttp2_session_send:[2,6,5,3],inlen:[3,6,5],recept:[2,6,5,3],crash:3,greater:[3,6],handl:[2,5],nghttp2_goawai:[3,6],handi:5,automat:[3,6],anyth:5,uf_port:5,mode:4,bump:[3,6],chunk:[3,6,5],nghttp2_err_temporal_callback_failur:[2,6,3],"static":[2,6,4,5,3],our:5,patch:[3,1],out:[2,1,3,4,5,6],variabl:4,req:[3,6],categori:[3,6,5],suitabl:[3,6],rel:2,field_data:5,recv_callback:[3,6],insid:4,releas:[0,1,3],could:[2,6,5,3],keep:[2,6,4,5,3],length:[2,6,4,5,3],outsid:[3,4],retain:[3,6],softwar:[2,6,5,1],addrinfo:2,date:4,prioriti:[3,6,5],intention:[3,6],unknown:[2,6,3],system:[2,5],messag:[3,6,5],attach:[2,5],termin:[2,6,4,5,3],ipv4:4,sa_handl:[2,5],enqueu:5,exactli:[2,4],nghttp2_err_header_comp:[3,6],see:[2,6,4,5,3],structur:[2,6,5,3],charact:[2,6,5,3],nghttp2_session_del:[2,6,5,3],bev:[2,5],ssl_new:[2,5],"function":[0,2,3,4,5,6],bufferevent_get_input:[2,5],corrupt:5,have:[2,6,4,5,3],tabl:[3,6,4],need:[3,6,4,5],ai_socktyp:2,"0x04":4,"0x05":4,"0x00":[3,6,4],nghttp2_err_flow_control:[3,6],nghttp2_refused_stream:[3,6],evbuffer_pullup:[2,5],which:[2,6,4,5,3],zlib:4,singl:[2,6,4,5,3],opaque_data_len:[3,6],unless:[3,6],bufferevent_openssl_socket_new:[2,5],settings_max_concurrent_stream:[2,6,4,5,3],stream_data:[2,5],deploi:4,"class":4,nghttp2_error_cod:[2,6,5,3],nghttp2_err_stream_id_not_avail:[3,6],url:[2,4],request:[2,6,4,5,3],uri:[4,5],pipe:2,determin:4,nghttp2_pack_settings_payload:[3,6],"0x0d":[3,6],"0x0a":[3,6],ssl_load_error_str:[2,5],text:4,bufferevent_get_output:[2,5],redirect:5,locat:5,should:[2,6,5,3],local:[3,6],meant:5,familiar:4,memcpi:[2,5],nghttp2_session_client_new2:[3,6],settings_initial_window_s:[3,6,4],nghttp2_data:[2,6,3],increas:[3,6,5],nghttp2_submit_respons:[2,6,3],enabl:[3,6,4],whether:[2,6,5,1],stuff:[3,6],contain:[2,6,4,5,3],nghttp2_window_upd:[3,6],frame:[2,6,4,5,3],knowledg:4,temporarili:[3,6],statu:[0,6,4,3,2],wire:[2,4,5],nghttp2_settings_entri:[2,6,5,3],written:[2,6,4,5,3],https_uri:5,nghttp2_initial_connection_window_s:[3,6],kei:[2,6,4,3],supporet:4,entir:[2,6,3],last_stream_id:[3,6,4],addit:[2,6,3],revers:4,nghttp2_proto_version_id:[2,6,5,3],equal:2,etc:[2,4,5],instanc:[3,6],uint16_t:[3,6,5],rfc2616:[3,6],commenc:5,respect:[3,6,5],nghttp2_recv_callback:[3,6],ssl_ctx_set_next_proto_select_cb:[3,6,5],insuffici:[3,6],compon:5,json:4,treat:[2,6,3],nghttp2_err_invalid_argu:[3,6],immedi:[3,6],nghttp2_hcat_head:[3,6],sock_stream:2,evconnlisten:2,on_header_callback:[2,6,5,3],nghttp2_frame_size_error:[3,6],defin:[2,6,5,1,3],eintr:2,helper:[3,6],on_request_recv:2,libxml2:4,squid:4,select_next_proto_cb:[3,6,5],archiv:[2,5],substanti:[2,6,5,1],incom:[2,6,4,3],let:[2,5],member:[2,6,3],python:[0,4],ifndef:[6,1],dyanmic:4,http:[0,1,2,3,4,5,6],hostnam:4,uf_host:5,dealloc:4,peer_max_concurrent_stream:[3,6],off:5,well:[2,5],app_context:2,inflatehd:4,exampl:[2,6,4,5,3],command:4,error_cod:[2,6,4,5,3],nghttp2_data_sourc:[2,6,3],usual:[3,6],paus:[3,6],less:[3,6],send_callback:[2,6,5,3],half:[3,6],obtain:[2,6,5,1],tcp:[2,5],web:[2,4],cert_fil:2,point:[2,6,5,3],priorit:[3,6],addrlen:2,add:[2,6,3],match:[2,5],gmt:4,know:[3,6],nva:[2,6,5,3],python3:4,resid:[2,5],like:[2,6,4,5,3],success:4,nghttp2_pri_lowest:[3,6],nghttp2_flag_end_head:[3,6],necessari:2,tlen:[3,6],page:[2,5],file_read_callback:2,suppli:[3,6],"export":2,nghttp2_session_get_effective_recv_data_length:[3,6],error_html:2,librari:[0,1,2,3,4,5,6],lead:[3,6],avoid:[2,6,5,3],octet:[2,5],overlap:[3,6],isxdigit:2,outgo:[2,6,3],nghttp2_session_upgrad:[3,6],delete_http2_stream_data:[2,5],"enum":[0,6,3],usag:[2,6,4,5,3],settings_payloadlen:[3,6],nghttp2_nv_compare_nam:[3,6],about:[2,6,5,3],actual:[2,6,5,3],socket:[2,4,5],nghttp2_gzip:[3,6],chrome:4,fals:4,ssl_tlsext_err_ok:[2,6,5,3],disabl:[3,6,4],own:[3,6],nghttp2_err_invalid_fram:[3,6],ssl_op_no_sslv2:[2,5],warranti:[2,6,5,1],automak:4,merg:[2,6,5,1],val:[2,5],ai_famili:2,transfer:[0,6,4,3],ssl_filetype_pem:2,much:2,buz:4,unexpect:[3,6],bufferevent_fre:[2,5],overflow:[3,6],highest:[3,6],buf:[2,6,3],count:[3,6],succe:[3,6],nghttp2_stream_clos:[3,6],nghttp2_info:[3,6],googlecod:[3,6],displai:4,asynchron:[3,6],limit:[2,6,5,1],otherwis:[2,1,3,4,5,6],problem:[3,6],sockaddr:2,nghttp2_on_frame_not_send_callback:[3,6],strndup:5,"int":[2,6,5,3],nghttp2_flag_end_stream:[2,6,3],allow:[3,6,4],percent:2,detail:[3,6],other:[2,6,5,1,3],futur:[3,6],rememb:[2,5],outlen_ptr:[3,6],stat:2,err_error_str:[2,5],nghttp2_opt_peer_max_concurrent_stream:[3,6],rel_path:2,proto_str:[3,6],debian:4,session_data:[2,5],sphinx:4,eof:[2,6,3],reliabl:[3,6],indirectli:3,rule:[3,6],portion:[2,6,5,1,3]},objtypes:{"0":"c:member","1":"c:macro","2":"c:type","3":"c:function"},titles:["nghttp2 - HTTP/2.0 C Library","nghttp2ver.h","Tutorial: HTTP/2.0 server","API Reference","nghttp2 - HTTP/2.0 C Library","Tutorial: HTTP/2.0 client","nghttp2.h"],objnames:{"0":["c","member","C member"],"1":["c","macro","C macro"],"2":["c","type","C type"],"3":["c","function","C function"]},filenames:["index","nghttp2ver.h","tutorial-server","apiref","package_README","tutorial-client","nghttp2.h"]}) \ No newline at end of file diff --git a/tutorial-client.html b/tutorial-client.html index adb0db9d..536135e2 100644 --- a/tutorial-client.html +++ b/tutorial-client.html @@ -8,7 +8,7 @@ - Tutorial: HTTP/2.0 client — nghttp2 0.3.0-DEV documentation + Tutorial: HTTP/2.0 client — nghttp2 0.4.0-DEV documentation @@ -23,7 +23,7 @@