Update doc
This commit is contained in:
parent
cd3337aed2
commit
3432a0bed9
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* Sphinx stylesheet -- basic theme.
|
* Sphinx stylesheet -- basic theme.
|
||||||
*
|
*
|
||||||
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
* :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
|
||||||
* :license: BSD, see LICENSE for details.
|
* :license: BSD, see LICENSE for details.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -89,6 +89,7 @@ div.sphinxsidebar #searchbox input[type="submit"] {
|
||||||
|
|
||||||
img {
|
img {
|
||||||
border: 0;
|
border: 0;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- search page ----------------------------------------------------------- */
|
/* -- search page ----------------------------------------------------------- */
|
||||||
|
@ -401,10 +402,6 @@ dl.glossary dt {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.refcount {
|
|
||||||
color: #060;
|
|
||||||
}
|
|
||||||
|
|
||||||
.optional {
|
.optional {
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* Sphinx JavaScript utilities for all documentation.
|
* Sphinx JavaScript utilities for all documentation.
|
||||||
*
|
*
|
||||||
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
* :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
|
||||||
* :license: BSD, see LICENSE for details.
|
* :license: BSD, see LICENSE for details.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -32,7 +32,7 @@ if (!window.console || !console.firebug) {
|
||||||
*/
|
*/
|
||||||
jQuery.urldecode = function(x) {
|
jQuery.urldecode = function(x) {
|
||||||
return decodeURIComponent(x).replace(/\+/g, ' ');
|
return decodeURIComponent(x).replace(/\+/g, ' ');
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* small helper function to urlencode strings
|
* small helper function to urlencode strings
|
||||||
|
@ -61,18 +61,6 @@ jQuery.getQueryParameters = function(s) {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* small function to check if an array contains
|
|
||||||
* a given item.
|
|
||||||
*/
|
|
||||||
jQuery.contains = function(arr, item) {
|
|
||||||
for (var i = 0; i < arr.length; i++) {
|
|
||||||
if (arr[i] == item)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* highlight a given string on a jquery object by wrapping it in
|
* highlight a given string on a jquery object by wrapping it in
|
||||||
* span elements with the given class name.
|
* span elements with the given class name.
|
||||||
|
@ -180,6 +168,9 @@ var Documentation = {
|
||||||
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
|
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
|
||||||
if (terms.length) {
|
if (terms.length) {
|
||||||
var body = $('div.body');
|
var body = $('div.body');
|
||||||
|
if (!body.length) {
|
||||||
|
body = $('body');
|
||||||
|
}
|
||||||
window.setTimeout(function() {
|
window.setTimeout(function() {
|
||||||
$.each(terms, function() {
|
$.each(terms, function() {
|
||||||
body.highlightText(this.toLowerCase(), 'highlighted');
|
body.highlightText(this.toLowerCase(), 'highlighted');
|
||||||
|
|
|
@ -4,38 +4,11 @@
|
||||||
*
|
*
|
||||||
* Sphinx JavaScript utilties for the full-text search.
|
* Sphinx JavaScript utilties for the full-text search.
|
||||||
*
|
*
|
||||||
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
* :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
|
||||||
* :license: BSD, see LICENSE for details.
|
* :license: BSD, see LICENSE for details.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* helper function to return a node containing the
|
|
||||||
* search summary for a given text. keywords is a list
|
|
||||||
* of stemmed words, hlwords is the list of normal, unstemmed
|
|
||||||
* words. the first one is used to find the occurance, the
|
|
||||||
* latter for highlighting it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
jQuery.makeSearchSummary = function(text, keywords, hlwords) {
|
|
||||||
var textLower = text.toLowerCase();
|
|
||||||
var start = 0;
|
|
||||||
$.each(keywords, function() {
|
|
||||||
var i = textLower.indexOf(this.toLowerCase());
|
|
||||||
if (i > -1)
|
|
||||||
start = i;
|
|
||||||
});
|
|
||||||
start = Math.max(start - 120, 0);
|
|
||||||
var excerpt = ((start > 0) ? '...' : '') +
|
|
||||||
$.trim(text.substr(start, 240)) +
|
|
||||||
((start + 240 - text.length) ? '...' : '');
|
|
||||||
var rv = $('<div class="context"></div>').text(excerpt);
|
|
||||||
$.each(hlwords, function() {
|
|
||||||
rv = rv.highlightText(this, 'highlighted');
|
|
||||||
});
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Porter Stemmer
|
* Porter Stemmer
|
||||||
|
@ -220,6 +193,38 @@ var Stemmer = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple result scoring code.
|
||||||
|
*/
|
||||||
|
var Scorer = {
|
||||||
|
// Implement the following function to further tweak the score for each result
|
||||||
|
// The function takes a result array [filename, title, anchor, descr, score]
|
||||||
|
// and returns the new score.
|
||||||
|
/*
|
||||||
|
score: function(result) {
|
||||||
|
return result[4];
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
// query matches the full name of an object
|
||||||
|
objNameMatch: 11,
|
||||||
|
// or matches in the last dotted part of the object name
|
||||||
|
objPartialMatch: 6,
|
||||||
|
// Additive scores depending on the priority of the object
|
||||||
|
objPrio: {0: 15, // used to be importantResults
|
||||||
|
1: 5, // used to be objectResults
|
||||||
|
2: -5}, // used to be unimportantResults
|
||||||
|
// Used when the priority is not in the mapping.
|
||||||
|
objPrioDefault: 0,
|
||||||
|
|
||||||
|
// query found in title
|
||||||
|
title: 15,
|
||||||
|
// query found in terms
|
||||||
|
term: 5
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search Module
|
* Search Module
|
||||||
*/
|
*/
|
||||||
|
@ -239,8 +244,13 @@ var Search = {
|
||||||
},
|
},
|
||||||
|
|
||||||
loadIndex : function(url) {
|
loadIndex : function(url) {
|
||||||
$.ajax({type: "GET", url: url, data: null, success: null,
|
$.ajax({type: "GET", url: url, data: null,
|
||||||
dataType: "script", cache: true});
|
dataType: "script", cache: true,
|
||||||
|
complete: function(jqxhr, textstatus) {
|
||||||
|
if (textstatus != "success") {
|
||||||
|
document.getElementById("searchindexloader").src = url;
|
||||||
|
}
|
||||||
|
}});
|
||||||
},
|
},
|
||||||
|
|
||||||
setIndex : function(index) {
|
setIndex : function(index) {
|
||||||
|
@ -268,19 +278,20 @@ var Search = {
|
||||||
if (this._pulse_status >= 0)
|
if (this._pulse_status >= 0)
|
||||||
return;
|
return;
|
||||||
function pulse() {
|
function pulse() {
|
||||||
|
var i;
|
||||||
Search._pulse_status = (Search._pulse_status + 1) % 4;
|
Search._pulse_status = (Search._pulse_status + 1) % 4;
|
||||||
var dotString = '';
|
var dotString = '';
|
||||||
for (var i = 0; i < Search._pulse_status; i++)
|
for (i = 0; i < Search._pulse_status; i++)
|
||||||
dotString += '.';
|
dotString += '.';
|
||||||
Search.dots.text(dotString);
|
Search.dots.text(dotString);
|
||||||
if (Search._pulse_status > -1)
|
if (Search._pulse_status > -1)
|
||||||
window.setTimeout(pulse, 500);
|
window.setTimeout(pulse, 500);
|
||||||
};
|
}
|
||||||
pulse();
|
pulse();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* perform a search for something
|
* perform a search for something (or wait until index is loaded)
|
||||||
*/
|
*/
|
||||||
performSearch : function(query) {
|
performSearch : function(query) {
|
||||||
// create the required interface elements
|
// create the required interface elements
|
||||||
|
@ -300,41 +311,46 @@ var Search = {
|
||||||
this.deferQuery(query);
|
this.deferQuery(query);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* execute search (requires search index to be loaded)
|
||||||
|
*/
|
||||||
query : function(query) {
|
query : function(query) {
|
||||||
|
var i;
|
||||||
var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
|
var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
|
||||||
|
|
||||||
// Stem the searchterms and add them to the correct list
|
// stem the searchterms and add them to the correct list
|
||||||
var stemmer = new Stemmer();
|
var stemmer = new Stemmer();
|
||||||
var searchterms = [];
|
var searchterms = [];
|
||||||
var excluded = [];
|
var excluded = [];
|
||||||
var hlterms = [];
|
var hlterms = [];
|
||||||
var tmp = query.split(/\s+/);
|
var tmp = query.split(/\s+/);
|
||||||
var objectterms = [];
|
var objectterms = [];
|
||||||
for (var i = 0; i < tmp.length; i++) {
|
for (i = 0; i < tmp.length; i++) {
|
||||||
if (tmp[i] != "") {
|
if (tmp[i] !== "") {
|
||||||
objectterms.push(tmp[i].toLowerCase());
|
objectterms.push(tmp[i].toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($u.indexOf(stopwords, tmp[i]) != -1 || tmp[i].match(/^\d+$/) ||
|
if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
|
||||||
tmp[i] == "") {
|
tmp[i] === "") {
|
||||||
// skip this "word"
|
// skip this "word"
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// stem the word
|
// stem the word
|
||||||
var word = stemmer.stemWord(tmp[i]).toLowerCase();
|
var word = stemmer.stemWord(tmp[i].toLowerCase());
|
||||||
|
var toAppend;
|
||||||
// select the correct list
|
// select the correct list
|
||||||
if (word[0] == '-') {
|
if (word[0] == '-') {
|
||||||
var toAppend = excluded;
|
toAppend = excluded;
|
||||||
word = word.substr(1);
|
word = word.substr(1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var toAppend = searchterms;
|
toAppend = searchterms;
|
||||||
hlterms.push(tmp[i].toLowerCase());
|
hlterms.push(tmp[i].toLowerCase());
|
||||||
}
|
}
|
||||||
// only add if not already in the list
|
// only add if not already in the list
|
||||||
if (!$.contains(toAppend, word))
|
if (!$u.contains(toAppend, word))
|
||||||
toAppend.push(word);
|
toAppend.push(word);
|
||||||
};
|
}
|
||||||
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
|
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
|
||||||
|
|
||||||
// console.debug('SEARCH: searching for:');
|
// console.debug('SEARCH: searching for:');
|
||||||
|
@ -342,89 +358,51 @@ var Search = {
|
||||||
// console.info('excluded: ', excluded);
|
// console.info('excluded: ', excluded);
|
||||||
|
|
||||||
// prepare search
|
// prepare search
|
||||||
var filenames = this._index.filenames;
|
|
||||||
var titles = this._index.titles;
|
|
||||||
var terms = this._index.terms;
|
var terms = this._index.terms;
|
||||||
var fileMap = {};
|
var titleterms = this._index.titleterms;
|
||||||
var files = null;
|
|
||||||
// different result priorities
|
// array of [filename, title, anchor, descr, score]
|
||||||
var importantResults = [];
|
var results = [];
|
||||||
var objectResults = [];
|
|
||||||
var regularResults = [];
|
|
||||||
var unimportantResults = [];
|
|
||||||
$('#search-progress').empty();
|
$('#search-progress').empty();
|
||||||
|
|
||||||
// lookup as object
|
// lookup as object
|
||||||
for (var i = 0; i < objectterms.length; i++) {
|
for (i = 0; i < objectterms.length; i++) {
|
||||||
var others = [].concat(objectterms.slice(0,i),
|
var others = [].concat(objectterms.slice(0, i),
|
||||||
objectterms.slice(i+1, objectterms.length))
|
objectterms.slice(i+1, objectterms.length));
|
||||||
var results = this.performObjectSearch(objectterms[i], others);
|
results = results.concat(this.performObjectSearch(objectterms[i], others));
|
||||||
// Assume first word is most likely to be the object,
|
|
||||||
// other words more likely to be in description.
|
|
||||||
// Therefore put matches for earlier words first.
|
|
||||||
// (Results are eventually used in reverse order).
|
|
||||||
objectResults = results[0].concat(objectResults);
|
|
||||||
importantResults = results[1].concat(importantResults);
|
|
||||||
unimportantResults = results[2].concat(unimportantResults);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// perform the search on the required terms
|
// lookup as search terms in fulltext
|
||||||
for (var i = 0; i < searchterms.length; i++) {
|
results = results.concat(this.performTermsSearch(searchterms, excluded, terms, Scorer.term))
|
||||||
var word = searchterms[i];
|
.concat(this.performTermsSearch(searchterms, excluded, titleterms, Scorer.title));
|
||||||
// no match but word was a required one
|
|
||||||
if ((files = terms[word]) == null)
|
// let the scorer override scores with a custom scoring function
|
||||||
break;
|
if (Scorer.score) {
|
||||||
if (files.length == undefined) {
|
for (i = 0; i < results.length; i++)
|
||||||
files = [files];
|
results[i][4] = Scorer.score(results[i]);
|
||||||
}
|
|
||||||
// create the mapping
|
|
||||||
for (var j = 0; j < files.length; j++) {
|
|
||||||
var file = files[j];
|
|
||||||
if (file in fileMap)
|
|
||||||
fileMap[file].push(word);
|
|
||||||
else
|
|
||||||
fileMap[file] = [word];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check if the files don't contain excluded terms
|
// now sort the results by score (in opposite order of appearance, since the
|
||||||
for (var file in fileMap) {
|
// display function below uses pop() to retrieve items) and then
|
||||||
var valid = true;
|
// alphabetically
|
||||||
|
results.sort(function(a, b) {
|
||||||
// check if all requirements are matched
|
var left = a[4];
|
||||||
if (fileMap[file].length != searchterms.length)
|
var right = b[4];
|
||||||
continue;
|
if (left > right) {
|
||||||
|
return 1;
|
||||||
// ensure that none of the excluded terms is in the
|
} else if (left < right) {
|
||||||
// search result.
|
return -1;
|
||||||
for (var i = 0; i < excluded.length; i++) {
|
} else {
|
||||||
if (terms[excluded[i]] == file ||
|
// same score: sort alphabetically
|
||||||
$.contains(terms[excluded[i]] || [], file)) {
|
left = a[1].toLowerCase();
|
||||||
valid = false;
|
right = b[1].toLowerCase();
|
||||||
break;
|
return (left > right) ? -1 : ((left < right) ? 1 : 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have still a valid result we can add it
|
|
||||||
// to the result list
|
|
||||||
if (valid)
|
|
||||||
regularResults.push([filenames[file], titles[file], '', null]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete unused variables in order to not waste
|
|
||||||
// memory until list is retrieved completely
|
|
||||||
delete filenames, titles, terms;
|
|
||||||
|
|
||||||
// now sort the regular results descending by title
|
|
||||||
regularResults.sort(function(a, b) {
|
|
||||||
var left = a[1].toLowerCase();
|
|
||||||
var right = b[1].toLowerCase();
|
|
||||||
return (left > right) ? -1 : ((left < right) ? 1 : 0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// combine all results
|
// for debugging
|
||||||
var results = unimportantResults.concat(regularResults)
|
//Search.lastresults = results.slice(); // a copy
|
||||||
.concat(objectResults).concat(importantResults);
|
//console.info('search results:', Search.lastresults);
|
||||||
|
|
||||||
// print the results
|
// print the results
|
||||||
var resultCount = results.length;
|
var resultCount = results.length;
|
||||||
|
@ -433,7 +411,7 @@ var Search = {
|
||||||
if (results.length) {
|
if (results.length) {
|
||||||
var item = results.pop();
|
var item = results.pop();
|
||||||
var listItem = $('<li style="display:none"></li>');
|
var listItem = $('<li style="display:none"></li>');
|
||||||
if (DOCUMENTATION_OPTIONS.FILE_SUFFIX == '') {
|
if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') {
|
||||||
// dirhtml builder
|
// dirhtml builder
|
||||||
var dirname = item[0] + '/';
|
var dirname = item[0] + '/';
|
||||||
if (dirname.match(/\/index\/$/)) {
|
if (dirname.match(/\/index\/$/)) {
|
||||||
|
@ -457,16 +435,18 @@ var Search = {
|
||||||
displayNextItem();
|
displayNextItem();
|
||||||
});
|
});
|
||||||
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
||||||
$.get(DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' +
|
$.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.txt',
|
||||||
item[0] + '.txt', function(data) {
|
dataType: "text",
|
||||||
if (data != '') {
|
complete: function(jqxhr, textstatus) {
|
||||||
listItem.append($.makeSearchSummary(data, searchterms, hlterms));
|
var data = jqxhr.responseText;
|
||||||
Search.output.append(listItem);
|
if (data !== '') {
|
||||||
}
|
listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
|
||||||
listItem.slideDown(5, function() {
|
}
|
||||||
displayNextItem();
|
Search.output.append(listItem);
|
||||||
});
|
listItem.slideDown(5, function() {
|
||||||
}, "text");
|
displayNextItem();
|
||||||
|
});
|
||||||
|
}});
|
||||||
} else {
|
} else {
|
||||||
// no source available, just display title
|
// no source available, just display title
|
||||||
Search.output.append(listItem);
|
Search.output.append(listItem);
|
||||||
|
@ -489,20 +469,32 @@ var Search = {
|
||||||
displayNextItem();
|
displayNextItem();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* search for object names
|
||||||
|
*/
|
||||||
performObjectSearch : function(object, otherterms) {
|
performObjectSearch : function(object, otherterms) {
|
||||||
var filenames = this._index.filenames;
|
var filenames = this._index.filenames;
|
||||||
var objects = this._index.objects;
|
var objects = this._index.objects;
|
||||||
var objnames = this._index.objnames;
|
var objnames = this._index.objnames;
|
||||||
var titles = this._index.titles;
|
var titles = this._index.titles;
|
||||||
|
|
||||||
var importantResults = [];
|
var i;
|
||||||
var objectResults = [];
|
var results = [];
|
||||||
var unimportantResults = [];
|
|
||||||
|
|
||||||
for (var prefix in objects) {
|
for (var prefix in objects) {
|
||||||
for (var name in objects[prefix]) {
|
for (var name in objects[prefix]) {
|
||||||
var fullname = (prefix ? prefix + '.' : '') + name;
|
var fullname = (prefix ? prefix + '.' : '') + name;
|
||||||
if (fullname.toLowerCase().indexOf(object) > -1) {
|
if (fullname.toLowerCase().indexOf(object) > -1) {
|
||||||
|
var score = 0;
|
||||||
|
var parts = fullname.split('.');
|
||||||
|
// check for different match types: exact matches of full name or
|
||||||
|
// "last name" (i.e. last dotted part)
|
||||||
|
if (fullname == object || parts[parts.length - 1] == object) {
|
||||||
|
score += Scorer.objNameMatch;
|
||||||
|
// matches in last name
|
||||||
|
} else if (parts[parts.length - 1].indexOf(object) > -1) {
|
||||||
|
score += Scorer.objPartialMatch;
|
||||||
|
}
|
||||||
var match = objects[prefix][name];
|
var match = objects[prefix][name];
|
||||||
var objname = objnames[match[1]][2];
|
var objname = objnames[match[1]][2];
|
||||||
var title = titles[match[0]];
|
var title = titles[match[0]];
|
||||||
|
@ -512,7 +504,7 @@ var Search = {
|
||||||
var haystack = (prefix + ' ' + name + ' ' +
|
var haystack = (prefix + ' ' + name + ' ' +
|
||||||
objname + ' ' + title).toLowerCase();
|
objname + ' ' + title).toLowerCase();
|
||||||
var allfound = true;
|
var allfound = true;
|
||||||
for (var i = 0; i < otherterms.length; i++) {
|
for (i = 0; i < otherterms.length; i++) {
|
||||||
if (haystack.indexOf(otherterms[i]) == -1) {
|
if (haystack.indexOf(otherterms[i]) == -1) {
|
||||||
allfound = false;
|
allfound = false;
|
||||||
break;
|
break;
|
||||||
|
@ -523,37 +515,107 @@ var Search = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var descr = objname + _(', in ') + title;
|
var descr = objname + _(', in ') + title;
|
||||||
anchor = match[3];
|
|
||||||
if (anchor == '')
|
var anchor = match[3];
|
||||||
|
if (anchor === '')
|
||||||
anchor = fullname;
|
anchor = fullname;
|
||||||
else if (anchor == '-')
|
else if (anchor == '-')
|
||||||
anchor = objnames[match[1]][1] + '-' + fullname;
|
anchor = objnames[match[1]][1] + '-' + fullname;
|
||||||
result = [filenames[match[0]], fullname, '#'+anchor, descr];
|
// add custom score for some objects according to scorer
|
||||||
switch (match[2]) {
|
if (Scorer.objPrio.hasOwnProperty(match[2])) {
|
||||||
case 1: objectResults.push(result); break;
|
score += Scorer.objPrio[match[2]];
|
||||||
case 0: importantResults.push(result); break;
|
} else {
|
||||||
case 2: unimportantResults.push(result); break;
|
score += Scorer.objPrioDefault;
|
||||||
}
|
}
|
||||||
|
results.push([filenames[match[0]], fullname, '#'+anchor, descr, score]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort results descending
|
return results;
|
||||||
objectResults.sort(function(a, b) {
|
},
|
||||||
return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
importantResults.sort(function(a, b) {
|
/**
|
||||||
return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
|
* search for full-text terms in the index
|
||||||
});
|
*/
|
||||||
|
performTermsSearch : function(searchterms, excluded, terms, score) {
|
||||||
|
var filenames = this._index.filenames;
|
||||||
|
var titles = this._index.titles;
|
||||||
|
|
||||||
unimportantResults.sort(function(a, b) {
|
var i, j, file, files;
|
||||||
return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
|
var fileMap = {};
|
||||||
});
|
var results = [];
|
||||||
|
|
||||||
return [importantResults, objectResults, unimportantResults]
|
// perform the search on the required terms
|
||||||
|
for (i = 0; i < searchterms.length; i++) {
|
||||||
|
var word = searchterms[i];
|
||||||
|
// no match but word was a required one
|
||||||
|
if ((files = terms[word]) === undefined)
|
||||||
|
break;
|
||||||
|
if (files.length === undefined) {
|
||||||
|
files = [files];
|
||||||
|
}
|
||||||
|
// create the mapping
|
||||||
|
for (j = 0; j < files.length; j++) {
|
||||||
|
file = files[j];
|
||||||
|
if (file in fileMap)
|
||||||
|
fileMap[file].push(word);
|
||||||
|
else
|
||||||
|
fileMap[file] = [word];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now check if the files don't contain excluded terms
|
||||||
|
for (file in fileMap) {
|
||||||
|
var valid = true;
|
||||||
|
|
||||||
|
// check if all requirements are matched
|
||||||
|
if (fileMap[file].length != searchterms.length)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// ensure that none of the excluded terms is in the search result
|
||||||
|
for (i = 0; i < excluded.length; i++) {
|
||||||
|
if (terms[excluded[i]] == file ||
|
||||||
|
$u.contains(terms[excluded[i]] || [], file)) {
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have still a valid result we can add it to the result list
|
||||||
|
if (valid) {
|
||||||
|
results.push([filenames[file], titles[file], '', null, score]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper function to return a node containing the
|
||||||
|
* search summary for a given text. keywords is a list
|
||||||
|
* of stemmed words, hlwords is the list of normal, unstemmed
|
||||||
|
* words. the first one is used to find the occurance, the
|
||||||
|
* latter for highlighting it.
|
||||||
|
*/
|
||||||
|
makeSearchSummary : function(text, keywords, hlwords) {
|
||||||
|
var textLower = text.toLowerCase();
|
||||||
|
var start = 0;
|
||||||
|
$.each(keywords, function() {
|
||||||
|
var i = textLower.indexOf(this.toLowerCase());
|
||||||
|
if (i > -1)
|
||||||
|
start = i;
|
||||||
|
});
|
||||||
|
start = Math.max(start - 120, 0);
|
||||||
|
var excerpt = ((start > 0) ? '...' : '') +
|
||||||
|
$.trim(text.substr(start, 240)) +
|
||||||
|
((start + 240 - text.length) ? '...' : '');
|
||||||
|
var rv = $('<div class="context"></div>').text(excerpt);
|
||||||
|
$.each(hlwords, function() {
|
||||||
|
rv = rv.highlightText(this, 'highlighted');
|
||||||
|
});
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
Search.init();
|
Search.init();
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* sphinx.websupport utilties for all documentation.
|
* sphinx.websupport utilties for all documentation.
|
||||||
*
|
*
|
||||||
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
* :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
|
||||||
* :license: BSD, see LICENSE for details.
|
* :license: BSD, see LICENSE for details.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
1499
apiref.html
1499
apiref.html
File diff suppressed because it is too large
Load Diff
488
genindex.html
488
genindex.html
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
||||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||||||
|
@ -22,7 +21,7 @@
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT:'',
|
URL_ROOT:'./',
|
||||||
VERSION:'0.4.0-DEV',
|
VERSION:'0.4.0-DEV',
|
||||||
COLLAPSE_INDEX:false,
|
COLLAPSE_INDEX:false,
|
||||||
FILE_SUFFIX:'.html',
|
FILE_SUFFIX:'.html',
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
||||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||||||
|
@ -22,7 +21,7 @@
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT:'',
|
URL_ROOT:'./',
|
||||||
VERSION:'0.4.0-DEV',
|
VERSION:'0.4.0-DEV',
|
||||||
COLLAPSE_INDEX:false,
|
COLLAPSE_INDEX:false,
|
||||||
FILE_SUFFIX:'.html',
|
FILE_SUFFIX:'.html',
|
||||||
|
@ -2290,6 +2289,13 @@
|
||||||
<span class="cm"> * This function creates copies of all name/value pairs in |nva|. It</span>
|
<span class="cm"> * This function creates copies of all name/value pairs in |nva|. It</span>
|
||||||
<span class="cm"> * also lower-cases all names in |nva|.</span>
|
<span class="cm"> * also lower-cases all names in |nva|.</span>
|
||||||
<span class="cm"> *</span>
|
<span class="cm"> *</span>
|
||||||
|
<span class="cm"> * The |promised_stream_user_data| is a pointer to an arbitrary data</span>
|
||||||
|
<span class="cm"> * which is associated to the promised stream this frame will open and</span>
|
||||||
|
<span class="cm"> * make it in reserved state. It is available using</span>
|
||||||
|
<span class="cm"> * `nghttp2_session_get_stream_user_data()`. The application can</span>
|
||||||
|
<span class="cm"> * access it in :type:`nghttp2_before_frame_send_callback` and</span>
|
||||||
|
<span class="cm"> * :type:`nghttp2_on_frame_send_callback` of this frame.</span>
|
||||||
|
<span class="cm"> *</span>
|
||||||
<span class="cm"> * Since the library reorders the frames and tries to send the highest</span>
|
<span class="cm"> * Since the library reorders the frames and tries to send the highest</span>
|
||||||
<span class="cm"> * prioritized one first and the HTTP/2.0 specification requires the</span>
|
<span class="cm"> * prioritized one first and the HTTP/2.0 specification requires the</span>
|
||||||
<span class="cm"> * stream ID must be strictly increasing, the promised stream ID</span>
|
<span class="cm"> * stream ID must be strictly increasing, the promised stream ID</span>
|
||||||
|
@ -2310,7 +2316,8 @@
|
||||||
<span class="cm"> */</span>
|
<span class="cm"> */</span>
|
||||||
<span class="kt">int</span> <span class="nf">nghttp2_submit_push_promise</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">flags</span><span class="p">,</span>
|
<span class="kt">int</span> <span class="nf">nghttp2_submit_push_promise</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">flags</span><span class="p">,</span>
|
||||||
<span class="kt">int32_t</span> <span class="n">stream_id</span><span class="p">,</span>
|
<span class="kt">int32_t</span> <span class="n">stream_id</span><span class="p">,</span>
|
||||||
<span class="k">const</span> <span class="n">nghttp2_nv</span> <span class="o">*</span><span class="n">nva</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">nvlen</span><span class="p">);</span>
|
<span class="k">const</span> <span class="n">nghttp2_nv</span> <span class="o">*</span><span class="n">nva</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">nvlen</span><span class="p">,</span>
|
||||||
|
<span class="kt">void</span> <span class="o">*</span><span class="n">promised_stream_user_data</span><span class="p">);</span>
|
||||||
|
|
||||||
<span class="cm">/**</span>
|
<span class="cm">/**</span>
|
||||||
<span class="cm"> * @function</span>
|
<span class="cm"> * @function</span>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
||||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||||||
|
@ -22,7 +21,7 @@
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT:'',
|
URL_ROOT:'./',
|
||||||
VERSION:'0.4.0-DEV',
|
VERSION:'0.4.0-DEV',
|
||||||
COLLAPSE_INDEX:false,
|
COLLAPSE_INDEX:false,
|
||||||
FILE_SUFFIX:'.html',
|
FILE_SUFFIX:'.html',
|
||||||
|
|
BIN
objects.inv
BIN
objects.inv
Binary file not shown.
|
@ -1,6 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
||||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||||||
|
@ -22,7 +21,7 @@
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT:'',
|
URL_ROOT:'./',
|
||||||
VERSION:'0.4.0-DEV',
|
VERSION:'0.4.0-DEV',
|
||||||
COLLAPSE_INDEX:false,
|
COLLAPSE_INDEX:false,
|
||||||
FILE_SUFFIX:'.html',
|
FILE_SUFFIX:'.html',
|
||||||
|
@ -271,11 +270,12 @@ installed:</p>
|
||||||
<h2>Build from git<a class="headerlink" href="#build-from-git" title="Permalink to this headline">¶</a></h2>
|
<h2>Build from git<a class="headerlink" href="#build-from-git" title="Permalink to this headline">¶</a></h2>
|
||||||
<p>Building from git is easy, but please be sure that at least autoconf 2.68 is
|
<p>Building from git is easy, but please be sure that at least autoconf 2.68 is
|
||||||
used:</p>
|
used:</p>
|
||||||
<div class="highlight-c"><pre>$ autoreconf -i
|
<div class="highlight-c"><div class="highlight"><pre>$ autoreconf -i
|
||||||
$ automake
|
$ automake
|
||||||
$ autoconf
|
$ autoconf
|
||||||
$ ./configure
|
$ ./configure
|
||||||
$ make</pre>
|
$ make
|
||||||
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="building-documentation">
|
<div class="section" id="building-documentation">
|
||||||
|
@ -285,7 +285,8 @@ $ make</pre>
|
||||||
<p class="last">Documentation is still incomplete.</p>
|
<p class="last">Documentation is still incomplete.</p>
|
||||||
</div>
|
</div>
|
||||||
<p>To build documentation, run:</p>
|
<p>To build documentation, run:</p>
|
||||||
<div class="highlight-c"><pre>$ make html</pre>
|
<div class="highlight-c"><div class="highlight"><pre>$ make html
|
||||||
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>The documents will be generated under <tt class="docutils literal"><span class="pre">doc/manual/html/</span></tt>.</p>
|
<p>The documents will be generated under <tt class="docutils literal"><span class="pre">doc/manual/html/</span></tt>.</p>
|
||||||
<p>The generated documents will not be installed with <tt class="docutils literal"><span class="pre">make</span> <span class="pre">install</span></tt>.</p>
|
<p>The generated documents will not be installed with <tt class="docutils literal"><span class="pre">make</span> <span class="pre">install</span></tt>.</p>
|
||||||
|
@ -301,7 +302,7 @@ $ make</pre>
|
||||||
with prior knowledge, HTTP Upgrade and NPN/ALPN TLS extension.</p>
|
with prior knowledge, HTTP Upgrade and NPN/ALPN TLS extension.</p>
|
||||||
<p>It has verbose output mode for framing information. Here is sample
|
<p>It has verbose output mode for framing information. Here is sample
|
||||||
output from <tt class="docutils literal"><span class="pre">nghttp</span></tt> client:</p>
|
output from <tt class="docutils literal"><span class="pre">nghttp</span></tt> client:</p>
|
||||||
<div class="highlight-c"><pre>$ src/nghttp -nv https://localhost:8443
|
<div class="highlight-c"><div class="highlight"><pre>$ src/nghttp -nv https://localhost:8443
|
||||||
[ 0.004][NPN] server offers:
|
[ 0.004][NPN] server offers:
|
||||||
* h2-10
|
* h2-10
|
||||||
* spdy/3.1
|
* spdy/3.1
|
||||||
|
@ -341,7 +342,7 @@ The negotiated protocol: h2-10
|
||||||
[ 0.008] (stream_id=1) content-length: 146
|
[ 0.008] (stream_id=1) content-length: 146
|
||||||
[ 0.008] (stream_id=1) content-type: text/html
|
[ 0.008] (stream_id=1) content-type: text/html
|
||||||
[ 0.008] (stream_id=1) date: Sat, 15 Feb 2014 08:14:12 GMT
|
[ 0.008] (stream_id=1) date: Sat, 15 Feb 2014 08:14:12 GMT
|
||||||
[ 0.008] (stream_id=1) etag: "b1-4e5535a027780-gzip"
|
[ 0.008] (stream_id=1) etag: "b1-4e5535a027780-gzip"
|
||||||
[ 0.008] (stream_id=1) last-modified: Sun, 01 Sep 2013 14:34:22 GMT
|
[ 0.008] (stream_id=1) last-modified: Sun, 01 Sep 2013 14:34:22 GMT
|
||||||
[ 0.008] (stream_id=1) server: Apache/2.4.6 (Debian)
|
[ 0.008] (stream_id=1) server: Apache/2.4.6 (Debian)
|
||||||
[ 0.008] (stream_id=1) vary: Accept-Encoding
|
[ 0.008] (stream_id=1) vary: Accept-Encoding
|
||||||
|
@ -354,10 +355,11 @@ The negotiated protocol: h2-10
|
||||||
[ 0.008] recv DATA frame <length=0, flags=0x01, stream_id=1>
|
[ 0.008] recv DATA frame <length=0, flags=0x01, stream_id=1>
|
||||||
; END_STREAM
|
; END_STREAM
|
||||||
[ 0.008] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
[ 0.008] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
||||||
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])</pre>
|
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
||||||
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>The HTTP Upgrade is performed like this:</p>
|
<p>The HTTP Upgrade is performed like this:</p>
|
||||||
<div class="highlight-c"><pre>$ src/nghttp -nvu http://localhost:8080
|
<div class="highlight-c"><div class="highlight"><pre>$ src/nghttp -nvu http://localhost:8080
|
||||||
[ 0.000] HTTP Upgrade request
|
[ 0.000] HTTP Upgrade request
|
||||||
GET / HTTP/1.1
|
GET / HTTP/1.1
|
||||||
Host: localhost:8080
|
Host: localhost:8080
|
||||||
|
@ -389,7 +391,7 @@ Upgrade: h2-10
|
||||||
[ 0.001] (stream_id=1) content-length: 177
|
[ 0.001] (stream_id=1) content-length: 177
|
||||||
[ 0.001] (stream_id=1) content-type: text/html
|
[ 0.001] (stream_id=1) content-type: text/html
|
||||||
[ 0.001] (stream_id=1) date: Sat, 15 Feb 2014 08:16:23 GMT
|
[ 0.001] (stream_id=1) date: Sat, 15 Feb 2014 08:16:23 GMT
|
||||||
[ 0.001] (stream_id=1) etag: "b1-4e5535a027780"
|
[ 0.001] (stream_id=1) etag: "b1-4e5535a027780"
|
||||||
[ 0.001] (stream_id=1) last-modified: Sun, 01 Sep 2013 14:34:22 GMT
|
[ 0.001] (stream_id=1) last-modified: Sun, 01 Sep 2013 14:34:22 GMT
|
||||||
[ 0.001] (stream_id=1) server: Apache/2.4.6 (Debian)
|
[ 0.001] (stream_id=1) server: Apache/2.4.6 (Debian)
|
||||||
[ 0.001] (stream_id=1) vary: Accept-Encoding
|
[ 0.001] (stream_id=1) vary: Accept-Encoding
|
||||||
|
@ -408,7 +410,8 @@ Upgrade: h2-10
|
||||||
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
||||||
[ 0.002] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
[ 0.002] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||||
; ACK
|
; ACK
|
||||||
(niv=0)</pre>
|
(niv=0)
|
||||||
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="nghttpd-server">
|
<div class="section" id="nghttpd-server">
|
||||||
|
@ -422,7 +425,7 @@ HTTP/2.0 connection. No HTTP Upgrade is supported.</p>
|
||||||
<p><tt class="docutils literal"><span class="pre">-p</span></tt> option allows users to configure server push.</p>
|
<p><tt class="docutils literal"><span class="pre">-p</span></tt> option allows users to configure server push.</p>
|
||||||
<p>Just like <tt class="docutils literal"><span class="pre">nghttp</span></tt>, it has verbose output mode for framing
|
<p>Just like <tt class="docutils literal"><span class="pre">nghttp</span></tt>, it has verbose output mode for framing
|
||||||
information. Here is sample output from <tt class="docutils literal"><span class="pre">nghttpd</span></tt> server:</p>
|
information. Here is sample output from <tt class="docutils literal"><span class="pre">nghttpd</span></tt> server:</p>
|
||||||
<div class="highlight-c"><pre>$ src/nghttpd --no-tls -v 8080
|
<div class="highlight-c"><div class="highlight"><pre>$ src/nghttpd --no-tls -v 8080
|
||||||
IPv4: listen on port 8080
|
IPv4: listen on port 8080
|
||||||
IPv6: listen on port 8080
|
IPv6: listen on port 8080
|
||||||
[id=1] [ 1.027] send SETTINGS frame <length=10, flags=0x00, stream_id=0>
|
[id=1] [ 1.027] send SETTINGS frame <length=10, flags=0x00, stream_id=0>
|
||||||
|
@ -465,7 +468,8 @@ IPv6: listen on port 8080
|
||||||
(niv=0)
|
(niv=0)
|
||||||
[id=1] [ 1.028] recv GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
[id=1] [ 1.028] recv GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
||||||
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
||||||
[id=1] [ 1.028] closed</pre>
|
[id=1] [ 1.028] closed
|
||||||
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="nghttpx-proxy">
|
<div class="section" id="nghttpx-proxy">
|
||||||
|
@ -555,7 +559,8 @@ create proxy.pac script like this:</p>
|
||||||
machine nghttpx is running. Please note that Chrome requires valid
|
machine nghttpx is running. Please note that Chrome requires valid
|
||||||
certificate for secure proxy.</p>
|
certificate for secure proxy.</p>
|
||||||
<p>Then run chrome with the following arguments:</p>
|
<p>Then run chrome with the following arguments:</p>
|
||||||
<div class="highlight-c"><pre>$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn</pre>
|
<div class="highlight-c"><div class="highlight"><pre>$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
|
||||||
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>With <tt class="docutils literal"><span class="pre">--http2-bridge</span></tt>, it accepts HTTP/2.0, SPDY and HTTP/1.1
|
<p>With <tt class="docutils literal"><span class="pre">--http2-bridge</span></tt>, it accepts HTTP/2.0, SPDY and HTTP/1.1
|
||||||
connections and communicates with backend in HTTP/2.0:</p>
|
connections and communicates with backend in HTTP/2.0:</p>
|
||||||
|
@ -1002,16 +1007,14 @@ corresponding header set was processed. The format is the same as
|
||||||
<div class="section" id="python-bindings">
|
<div class="section" id="python-bindings">
|
||||||
<h2>Python bindings<a class="headerlink" href="#python-bindings" title="Permalink to this headline">¶</a></h2>
|
<h2>Python bindings<a class="headerlink" href="#python-bindings" title="Permalink to this headline">¶</a></h2>
|
||||||
<p>This <tt class="docutils literal"><span class="pre">python</span></tt> directory contains nghttp2 Python bindings. The
|
<p>This <tt class="docutils literal"><span class="pre">python</span></tt> directory contains nghttp2 Python bindings. The
|
||||||
bindings currently only provide HPACK compressor and decompressor
|
bindings currently provide HPACK compressor and decompressor
|
||||||
classes.</p>
|
classes and HTTP/2 server.</p>
|
||||||
<p>The extension module is called <tt class="docutils literal"><span class="pre">nghttp2</span></tt>.</p>
|
<p>The extension module is called <tt class="docutils literal"><span class="pre">nghttp2</span></tt>.</p>
|
||||||
<p><tt class="docutils literal"><span class="pre">make</span></tt> will build the bindings and target Python version is
|
<p><tt class="docutils literal"><span class="pre">make</span></tt> will build the bindings and target Python version is
|
||||||
determined by configure script. If the detected Python version is not
|
determined by configure script. If the detected Python version is not
|
||||||
what you expect, specify a path to Python executable in <tt class="docutils literal"><span class="pre">PYTHON</span></tt>
|
what you expect, specify a path to Python executable in <tt class="docutils literal"><span class="pre">PYTHON</span></tt>
|
||||||
variable as an argument to configure script (e.g., <tt class="docutils literal"><span class="pre">./configure</span>
|
variable as an argument to configure script (e.g., <tt class="docutils literal"><span class="pre">./configure</span>
|
||||||
<span class="pre">PYTHON=/usr/bin/python3.3</span></tt>).</p>
|
<span class="pre">PYTHON=/usr/bin/python3.3</span></tt>).</p>
|
||||||
<div class="section" id="example">
|
|
||||||
<h3>Example<a class="headerlink" href="#example" title="Permalink to this headline">¶</a></h3>
|
|
||||||
<p>The following example code illustrates basic usage of HPACK compressor
|
<p>The following example code illustrates basic usage of HPACK compressor
|
||||||
and decompressor in Python:</p>
|
and decompressor in Python:</p>
|
||||||
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">binascii</span>
|
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">binascii</span>
|
||||||
|
@ -1028,6 +1031,74 @@ and decompressor in Python:</p>
|
||||||
<span class="k">print</span><span class="p">(</span><span class="n">hdrs</span><span class="p">)</span>
|
<span class="k">print</span><span class="p">(</span><span class="n">hdrs</span><span class="p">)</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
|
<p>The <tt class="docutils literal"><span class="pre">nghttp2.HTTP2Server</span></tt> class builds on top of the asyncio event
|
||||||
|
loop. On construction, <em>RequestHandlerClass</em> must be given, which must
|
||||||
|
be a subclass of <tt class="docutils literal"><span class="pre">nghttp2.BaseRequestHandler</span></tt> class.</p>
|
||||||
|
<p>The <tt class="docutils literal"><span class="pre">BaseRequestHandler</span></tt> class is used to handle the HTTP/2
|
||||||
|
stream. By default, it does not nothing. It must be subclassed to
|
||||||
|
handle each event callback method.</p>
|
||||||
|
<p>The first callback method invoked is <tt class="docutils literal"><span class="pre">on_headers()</span></tt>. It is called
|
||||||
|
when HEADERS frame, which includes request header fields, is arrived.</p>
|
||||||
|
<p>If request has request body, <tt class="docutils literal"><span class="pre">on_data(data)</span></tt> is invoked for each
|
||||||
|
chunk of received data.</p>
|
||||||
|
<p>When whole request is received, <tt class="docutils literal"><span class="pre">on_request_done()</span></tt> is invoked.</p>
|
||||||
|
<p>When stream is closed, <tt class="docutils literal"><span class="pre">on_close(error_code)</span></tt> is called.</p>
|
||||||
|
<p>The application can send response using <tt class="docutils literal"><span class="pre">send_response()</span></tt> method. It
|
||||||
|
can be used in <tt class="docutils literal"><span class="pre">on_headers()</span></tt>, <tt class="docutils literal"><span class="pre">on_data()</span></tt> or
|
||||||
|
<tt class="docutils literal"><span class="pre">on_request_done()</span></tt>.</p>
|
||||||
|
<p>The application can push resource using <tt class="docutils literal"><span class="pre">push()</span></tt> method. It must be
|
||||||
|
used before <tt class="docutils literal"><span class="pre">send_response()</span></tt> call.</p>
|
||||||
|
<p>The following instance variables are available:</p>
|
||||||
|
<dl class="docutils">
|
||||||
|
<dt>client_address</dt>
|
||||||
|
<dd>Contains a tuple of the form (host, port) referring to the
|
||||||
|
client’s address.</dd>
|
||||||
|
<dt>stream_id</dt>
|
||||||
|
<dd>Stream ID of this stream</dd>
|
||||||
|
<dt>scheme</dt>
|
||||||
|
<dd>Scheme of the request URI. This is a value of :scheme header field.</dd>
|
||||||
|
<dt>method</dt>
|
||||||
|
<dd>Method of this stream. This is a value of :method header field.</dd>
|
||||||
|
<dt>host</dt>
|
||||||
|
<dd>This is a value of :authority or host header field.</dd>
|
||||||
|
<dt>path</dt>
|
||||||
|
<dd>This is a value of :path header field.</dd>
|
||||||
|
</dl>
|
||||||
|
<p>The following example illustrates the HTTP2Server and
|
||||||
|
BaseRequestHandler usage:</p>
|
||||||
|
<div class="highlight-python"><div class="highlight"><pre><span class="c">#!/usr/bin/env python</span>
|
||||||
|
|
||||||
|
<span class="kn">import</span> <span class="nn">io</span><span class="o">,</span> <span class="nn">ssl</span>
|
||||||
|
<span class="kn">from</span> <span class="nn">pprint</span> <span class="kn">import</span> <span class="n">pprint</span>
|
||||||
|
<span class="kn">import</span> <span class="nn">nghttp2</span>
|
||||||
|
|
||||||
|
<span class="k">class</span> <span class="nc">Handler</span><span class="p">(</span><span class="n">nghttp2</span><span class="o">.</span><span class="n">BaseRequestHandler</span><span class="p">):</span>
|
||||||
|
|
||||||
|
<span class="k">def</span> <span class="nf">on_headers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||||
|
<span class="bp">self</span><span class="o">.</span><span class="n">push</span><span class="p">(</span><span class="n">path</span><span class="o">=</span><span class="s">'/css/bootstrap.css'</span><span class="p">,</span>
|
||||||
|
<span class="n">request_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="n">b</span><span class="s">'content-length'</span><span class="p">,</span> <span class="n">b</span><span class="s">'3'</span><span class="p">)],</span>
|
||||||
|
<span class="n">status</span><span class="o">=</span><span class="mi">200</span><span class="p">,</span>
|
||||||
|
<span class="n">body</span><span class="o">=</span><span class="s">'foo'</span><span class="p">)</span>
|
||||||
|
|
||||||
|
<span class="bp">self</span><span class="o">.</span><span class="n">push</span><span class="p">(</span><span class="n">path</span><span class="o">=</span><span class="s">'/js/bootstrap.js'</span><span class="p">,</span>
|
||||||
|
<span class="n">method</span><span class="o">=</span><span class="s">'GET'</span><span class="p">,</span>
|
||||||
|
<span class="n">request_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="n">b</span><span class="s">'content-length'</span><span class="p">,</span> <span class="n">b</span><span class="s">'10'</span><span class="p">)],</span>
|
||||||
|
<span class="n">status</span><span class="o">=</span><span class="mi">200</span><span class="p">,</span>
|
||||||
|
<span class="n">body</span><span class="o">=</span><span class="s">'foobarbuzz'</span><span class="p">)</span>
|
||||||
|
|
||||||
|
<span class="bp">self</span><span class="o">.</span><span class="n">send_response</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="mi">200</span><span class="p">,</span>
|
||||||
|
<span class="n">headers</span> <span class="o">=</span> <span class="p">[(</span><span class="n">b</span><span class="s">'content-type'</span><span class="p">,</span> <span class="n">b</span><span class="s">'text/plain'</span><span class="p">)],</span>
|
||||||
|
<span class="n">body</span><span class="o">=</span><span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">(</span><span class="n">b</span><span class="s">'nghttp2-python FTW'</span><span class="p">))</span>
|
||||||
|
|
||||||
|
<span class="n">ctx</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">SSLContext</span><span class="p">(</span><span class="n">ssl</span><span class="o">.</span><span class="n">PROTOCOL_SSLv23</span><span class="p">)</span>
|
||||||
|
<span class="n">ctx</span><span class="o">.</span><span class="n">options</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">OP_ALL</span> <span class="o">|</span> <span class="n">ssl</span><span class="o">.</span><span class="n">OP_NO_SSLv2</span>
|
||||||
|
<span class="n">ctx</span><span class="o">.</span><span class="n">set_npn_protocols</span><span class="p">([</span><span class="s">'h2-10'</span><span class="p">])</span>
|
||||||
|
<span class="n">ctx</span><span class="o">.</span><span class="n">load_cert_chain</span><span class="p">(</span><span class="s">'server.crt'</span><span class="p">,</span> <span class="s">'server.key'</span><span class="p">)</span>
|
||||||
|
|
||||||
|
<span class="c"># give None to ssl to make the server non-SSL/TLS</span>
|
||||||
|
<span class="n">server</span> <span class="o">=</span> <span class="n">nghttp2</span><span class="o">.</span><span class="n">HTTP2Server</span><span class="p">((</span><span class="s">'127.0.0.1'</span><span class="p">,</span> <span class="mi">8443</span><span class="p">),</span> <span class="n">Handler</span><span class="p">,</span> <span class="n">ssl</span><span class="o">=</span><span class="n">ctx</span><span class="p">)</span>
|
||||||
|
<span class="n">server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
|
||||||
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT:'',
|
URL_ROOT:'./',
|
||||||
VERSION:'0.4.0-DEV',
|
VERSION:'0.4.0-DEV',
|
||||||
COLLAPSE_INDEX:false,
|
COLLAPSE_INDEX:false,
|
||||||
FILE_SUFFIX:'.html',
|
FILE_SUFFIX:'.html',
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
||||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||||||
|
@ -22,7 +21,7 @@
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT:'',
|
URL_ROOT:'./',
|
||||||
VERSION:'0.4.0-DEV',
|
VERSION:'0.4.0-DEV',
|
||||||
COLLAPSE_INDEX:false,
|
COLLAPSE_INDEX:false,
|
||||||
FILE_SUFFIX:'.html',
|
FILE_SUFFIX:'.html',
|
||||||
|
@ -154,7 +153,8 @@ the end of this page. It also resides in examples directory in the
|
||||||
archive or repository.</p>
|
archive or repository.</p>
|
||||||
<p>This simple client takes 1 argument, HTTPS URI, and retrieves the
|
<p>This simple client takes 1 argument, HTTPS URI, and retrieves the
|
||||||
resource denoted by the URI. Its synopsis is like this:</p>
|
resource denoted by the URI. Its synopsis is like this:</p>
|
||||||
<div class="highlight-c"><pre>$ libevent-client HTTPS_URI</pre>
|
<div class="highlight-c"><div class="highlight"><pre>$ libevent-client HTTPS_URI
|
||||||
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>We use libevent in this tutorial to handle networking I/O. Please
|
<p>We use libevent in this tutorial to handle networking I/O. Please
|
||||||
note that nghttp2 itself does not depend on libevent.</p>
|
note that nghttp2 itself does not depend on libevent.</p>
|
||||||
|
@ -163,7 +163,7 @@ function <tt class="docutils literal"><span class="pre">main()</span></tt> and <
|
||||||
library use. The one thing you should look at is setup NPN callback.
|
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
|
The NPN callback is used for the client to select the next application
|
||||||
protocol over the SSL/TLS transport. In this tutorial, we use
|
protocol over the SSL/TLS transport. In this tutorial, we use
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_select_next_protocol" title="nghttp2_select_next_protocol"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_select_next_protocol()</span></tt></a> function to select the HTTP/2.0
|
<a class="reference internal" href="apiref.html#c.nghttp2_select_next_protocol" title="nghttp2_select_next_protocol"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_select_next_protocol()</span></tt></a> function to select the HTTP/2.0
|
||||||
protocol the library supports:</p>
|
protocol the library supports:</p>
|
||||||
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">select_next_proto_cb</span><span class="p">(</span><span class="n">SSL</span><span class="o">*</span> <span class="n">ssl</span><span class="p">,</span>
|
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">select_next_proto_cb</span><span class="p">(</span><span class="n">SSL</span><span class="o">*</span> <span class="n">ssl</span><span class="p">,</span>
|
||||||
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">**</span><span class="n">out</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">outlen</span><span class="p">,</span>
|
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">**</span><span class="n">out</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">outlen</span><span class="p">,</span>
|
||||||
|
@ -310,15 +310,15 @@ finished successfully. We first initialize nghttp2 session object in
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>Since we are creating client, we use <a class="reference internal" href="apiref.html#nghttp2_session_client_new" title="nghttp2_session_client_new"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_client_new()</span></tt></a> to
|
<p>Since we are creating client, we use <a class="reference internal" href="apiref.html#c.nghttp2_session_client_new" title="nghttp2_session_client_new"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_client_new()</span></tt></a> to
|
||||||
initialize nghttp2 session object. We setup 7 callbacks for the
|
initialize nghttp2 session object. We setup 7 callbacks for the
|
||||||
nghttp2 session. We’ll explain these callbacks later.</p>
|
nghttp2 session. We’ll explain these callbacks later.</p>
|
||||||
<p>The <tt class="xref c c-func docutils literal"><span class="pre">delete_http2_session_data()</span></tt> destroys <tt class="docutils literal"><span class="pre">session_data</span></tt> and frees
|
<p>The <tt class="xref c c-func docutils literal"><span class="pre">delete_http2_session_data()</span></tt> destroys <tt class="docutils literal"><span class="pre">session_data</span></tt> and frees
|
||||||
its bufferevent, so it closes underlying connection as well. It also
|
its bufferevent, so it closes underlying connection as well. It also
|
||||||
calls <a class="reference internal" href="apiref.html#nghttp2_session_del" title="nghttp2_session_del"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_del()</span></tt></a> to delete nghttp2 session object.</p>
|
calls <a class="reference internal" href="apiref.html#c.nghttp2_session_del" title="nghttp2_session_del"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_del()</span></tt></a> to delete nghttp2 session object.</p>
|
||||||
<p>We begin HTTP/2.0 communication by sending client connection header,
|
<p>We begin HTTP/2.0 communication by sending client connection header,
|
||||||
which is 24 bytes magic byte sequence
|
which is 24 bytes magic byte sequence
|
||||||
(<a class="reference internal" href="apiref.html#NGHTTP2_CLIENT_CONNECTION_HEADER" title="NGHTTP2_CLIENT_CONNECTION_HEADER"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_CLIENT_CONNECTION_HEADER</span></tt></a>) followed by SETTINGS
|
(<a class="reference internal" href="apiref.html#c.NGHTTP2_CLIENT_CONNECTION_HEADER" title="NGHTTP2_CLIENT_CONNECTION_HEADER"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_CLIENT_CONNECTION_HEADER</span></tt></a>) followed by SETTINGS
|
||||||
frame. The transmission of client connection header is done in
|
frame. The transmission of client connection header is done in
|
||||||
<tt class="docutils literal"><span class="pre">send_client_connection_header()</span></tt>:</p>
|
<tt class="docutils literal"><span class="pre">send_client_connection_header()</span></tt>:</p>
|
||||||
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">void</span> <span class="nf">send_client_connection_header</span><span class="p">(</span><span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span><span class="p">)</span>
|
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">void</span> <span class="nf">send_client_connection_header</span><span class="p">(</span><span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span><span class="p">)</span>
|
||||||
|
@ -342,10 +342,10 @@ frame. The transmission of client connection header is done in
|
||||||
<p>Here we specify SETTINGS_MAX_CONCURRENT_STREAMS to 100, which is
|
<p>Here we specify SETTINGS_MAX_CONCURRENT_STREAMS to 100, which is
|
||||||
really not needed for this tiny example progoram, but we are
|
really not needed for this tiny example progoram, but we are
|
||||||
demonstrating the use of SETTINGS frame. To queue the SETTINGS frame
|
demonstrating the use of SETTINGS frame. To queue the SETTINGS frame
|
||||||
for the transmission, we use <a class="reference internal" href="apiref.html#nghttp2_submit_settings" title="nghttp2_submit_settings"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_settings()</span></tt></a>. Note that
|
for the transmission, we use <a class="reference internal" href="apiref.html#c.nghttp2_submit_settings" title="nghttp2_submit_settings"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_settings()</span></tt></a>. Note that
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_submit_settings" title="nghttp2_submit_settings"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_settings()</span></tt></a> function only queues the frame and not
|
<a class="reference internal" href="apiref.html#c.nghttp2_submit_settings" title="nghttp2_submit_settings"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_settings()</span></tt></a> function only queues the frame and not
|
||||||
actually send it. All <tt class="docutils literal"><span class="pre">nghttp2_submit_*()</span></tt> family functions have
|
actually send it. All <tt class="docutils literal"><span class="pre">nghttp2_submit_*()</span></tt> family functions have
|
||||||
this property. To actually send the frame, <a class="reference internal" href="apiref.html#nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> is
|
this property. To actually send the frame, <a class="reference internal" href="apiref.html#c.nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> is
|
||||||
used, which is described about later.</p>
|
used, which is described about later.</p>
|
||||||
<p>After the transmission of client connection header, we enqueue HTTP
|
<p>After the transmission of client connection header, we enqueue HTTP
|
||||||
request in <tt class="docutils literal"><span class="pre">submit_request()</span></tt> function:</p>
|
request in <tt class="docutils literal"><span class="pre">submit_request()</span></tt> function:</p>
|
||||||
|
@ -373,9 +373,9 @@ request in <tt class="docutils literal"><span class="pre">submit_request()</span
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>We build HTTP request header fields in <tt class="docutils literal"><span class="pre">hdrs</span></tt> which is an array of
|
<p>We build HTTP request header fields in <tt class="docutils literal"><span class="pre">hdrs</span></tt> which is an array of
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_nv" title="nghttp2_nv"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_nv</span></tt></a>. There are 4 header fields to be sent: <tt class="docutils literal"><span class="pre">:method</span></tt>,
|
<a class="reference internal" href="apiref.html#c.nghttp2_nv" title="nghttp2_nv"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_nv</span></tt></a>. There are 4 header fields to be sent: <tt class="docutils literal"><span class="pre">:method</span></tt>,
|
||||||
<tt class="docutils literal"><span class="pre">:scheme</span></tt>, <tt class="docutils literal"><span class="pre">:authority</span></tt> and <tt class="docutils literal"><span class="pre">:path</span></tt>. To queue this HTTP request,
|
<tt class="docutils literal"><span class="pre">:scheme</span></tt>, <tt class="docutils literal"><span class="pre">:authority</span></tt> and <tt class="docutils literal"><span class="pre">:path</span></tt>. To queue this HTTP request,
|
||||||
we use <a class="reference internal" href="apiref.html#nghttp2_submit_request" title="nghttp2_submit_request"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_request()</span></tt></a> function. The <tt class="xref c c-func docutils literal"><span class="pre">stream_data()</span></tt> is
|
we use <a class="reference internal" href="apiref.html#c.nghttp2_submit_request" title="nghttp2_submit_request"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_request()</span></tt></a> function. The <tt class="xref c c-func docutils literal"><span class="pre">stream_data()</span></tt> is
|
||||||
passed in <em>stream_user_data</em> parameter. It is used in nghttp2
|
passed in <em>stream_user_data</em> parameter. It is used in nghttp2
|
||||||
callbacks which we’ll describe about later.</p>
|
callbacks which we’ll describe about later.</p>
|
||||||
<p>The next bufferevent callback is <tt class="docutils literal"><span class="pre">readcb()</span></tt>, which is invoked when
|
<p>The next bufferevent callback is <tt class="docutils literal"><span class="pre">readcb()</span></tt>, which is invoked when
|
||||||
|
@ -402,8 +402,8 @@ data is available to read in the bufferevent input buffer:</p>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>In this function, we feed all unprocessed, received data to nghttp2
|
<p>In this function, we feed all unprocessed, received data to nghttp2
|
||||||
session object using <a class="reference internal" href="apiref.html#nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a> function. The
|
session object using <a class="reference internal" href="apiref.html#c.nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a> function. The
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a> processes the received data and may
|
<a class="reference internal" href="apiref.html#c.nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a> processes the received data and may
|
||||||
invoke nghttp2 callbacks and also queue frames. Since there may be
|
invoke nghttp2 callbacks and also queue frames. Since there may be
|
||||||
pending frames, we call <tt class="docutils literal"><span class="pre">session_send()</span></tt> function to send those
|
pending frames, we call <tt class="docutils literal"><span class="pre">session_send()</span></tt> function to send those
|
||||||
frames. The <tt class="docutils literal"><span class="pre">session_send()</span></tt> function is defined as follows:</p>
|
frames. The <tt class="docutils literal"><span class="pre">session_send()</span></tt> function is defined as follows:</p>
|
||||||
|
@ -420,10 +420,10 @@ frames. The <tt class="docutils literal"><span class="pre">session_send()</span>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>The <a class="reference internal" href="apiref.html#nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> function serializes the frame into wire
|
<p>The <a class="reference internal" href="apiref.html#c.nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> function serializes the frame into wire
|
||||||
format and call <a class="reference internal" href="apiref.html#nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> with
|
format and call <a class="reference internal" href="apiref.html#c.nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> with
|
||||||
it. We set <tt class="docutils literal"><span class="pre">send_callback()</span></tt> function to
|
it. We set <tt class="docutils literal"><span class="pre">send_callback()</span></tt> function to
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> in
|
<a class="reference internal" href="apiref.html#c.nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> in
|
||||||
<tt class="docutils literal"><span class="pre">initialize_nghttp2_session()</span></tt> function described earlier. It is
|
<tt class="docutils literal"><span class="pre">initialize_nghttp2_session()</span></tt> function described earlier. It is
|
||||||
defined as follows:</p>
|
defined as follows:</p>
|
||||||
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">ssize_t</span> <span class="nf">send_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
|
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">ssize_t</span> <span class="nf">send_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
|
||||||
|
@ -438,13 +438,13 @@ defined as follows:</p>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>Since we use bufferevent to abstract network I/O, we just write the
|
<p>Since we use bufferevent to abstract network I/O, we just write the
|
||||||
data to the bufferevent object. Note that <a class="reference internal" href="apiref.html#nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a>
|
data to the bufferevent object. Note that <a class="reference internal" href="apiref.html#c.nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a>
|
||||||
continues to write all frames queued so far. If we were writing the
|
continues to write all frames queued so far. If we were writing the
|
||||||
data to the non-blocking socket directly using <tt class="docutils literal"><span class="pre">write()</span></tt> system call
|
data to the non-blocking socket directly using <tt class="docutils literal"><span class="pre">write()</span></tt> system call
|
||||||
in the <a class="reference internal" href="apiref.html#nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a>, we will
|
in the <a class="reference internal" href="apiref.html#c.nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a>, we will
|
||||||
surely get <tt class="docutils literal"><span class="pre">EAGAIN</span></tt> or <tt class="docutils literal"><span class="pre">EWOULDBLOCK</span></tt> since the socket has limited
|
surely get <tt class="docutils literal"><span class="pre">EAGAIN</span></tt> or <tt class="docutils literal"><span class="pre">EWOULDBLOCK</span></tt> since the socket has limited
|
||||||
send buffer. If that happens, we can return
|
send buffer. If that happens, we can return
|
||||||
<a class="reference internal" href="apiref.html#NGHTTP2_ERR_WOULDBLOCK" title="NGHTTP2_ERR_WOULDBLOCK"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_WOULDBLOCK</span></tt></a> to signal the nghttp2 library to stop
|
<a class="reference internal" href="apiref.html#c.NGHTTP2_ERR_WOULDBLOCK" title="NGHTTP2_ERR_WOULDBLOCK"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_WOULDBLOCK</span></tt></a> to signal the nghttp2 library to stop
|
||||||
sending further data. But writing to the bufferevent, we have to
|
sending further data. But writing to the bufferevent, we have to
|
||||||
regulate the amount data to be buffered by ourselves to avoid possible
|
regulate the amount data to be buffered by ourselves to avoid possible
|
||||||
huge memory consumption. In this example client, we do not limit
|
huge memory consumption. In this example client, we do not limit
|
||||||
|
@ -469,8 +469,8 @@ we have to drop connection or not. The nghttp2 session object keeps
|
||||||
track of reception and transmission of GOAWAY frame and other error
|
track of reception and transmission of GOAWAY frame and other error
|
||||||
conditions as well. Using these information, nghttp2 session object
|
conditions as well. Using these information, nghttp2 session object
|
||||||
will tell whether the connection should be dropped or not. More
|
will tell whether the connection should be dropped or not. More
|
||||||
specifically, both <a class="reference internal" href="apiref.html#nghttp2_session_want_read" title="nghttp2_session_want_read"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_read()</span></tt></a> and
|
specifically, both <a class="reference internal" href="apiref.html#c.nghttp2_session_want_read" title="nghttp2_session_want_read"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_read()</span></tt></a> and
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_session_want_write" title="nghttp2_session_want_write"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_write()</span></tt></a> return 0, we have no business in the
|
<a class="reference internal" href="apiref.html#c.nghttp2_session_want_write" title="nghttp2_session_want_write"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_write()</span></tt></a> return 0, we have no business in the
|
||||||
connection. But since we are using bufferevent and its deferred
|
connection. But since we are using bufferevent and its deferred
|
||||||
callback option, the bufferevent output buffer may contain the pending
|
callback option, the bufferevent output buffer may contain the pending
|
||||||
data when the <tt class="docutils literal"><span class="pre">writecb()</span></tt> is called. To handle this situation, we
|
data when the <tt class="docutils literal"><span class="pre">writecb()</span></tt> is called. To handle this situation, we
|
||||||
|
@ -501,7 +501,7 @@ about to be sent:</p>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>Remember that we have not get stream ID when we submit HTTP request
|
<p>Remember that we have not get stream ID when we submit HTTP request
|
||||||
using <a class="reference internal" href="apiref.html#nghttp2_submit_request" title="nghttp2_submit_request"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_request()</span></tt></a>. Since nghttp2 library reorders the
|
using <a class="reference internal" href="apiref.html#c.nghttp2_submit_request" title="nghttp2_submit_request"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_request()</span></tt></a>. Since nghttp2 library reorders the
|
||||||
request based on priority and stream ID must be monotonically
|
request based on priority and stream ID must be monotonically
|
||||||
increased, the stream ID is not assigned just before transmission.
|
increased, the stream ID is not assigned just before transmission.
|
||||||
The one of the purpose of this callback is get the stream ID assigned
|
The one of the purpose of this callback is get the stream ID assigned
|
||||||
|
@ -510,11 +510,11 @@ 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).
|
HEADERS (which means that the first HEADERS frame to create a stream).
|
||||||
The assigned stream ID is <tt class="docutils literal"><span class="pre">frame->hd.stream_id</span></tt>. Recall that we
|
The assigned stream ID is <tt class="docutils literal"><span class="pre">frame->hd.stream_id</span></tt>. Recall that we
|
||||||
passed <tt class="docutils literal"><span class="pre">stream_data</span></tt> in the <em>stream_user_data</em> parameter of
|
passed <tt class="docutils literal"><span class="pre">stream_data</span></tt> in the <em>stream_user_data</em> parameter of
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_submit_request" title="nghttp2_submit_request"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_request()</span></tt></a> function. We can get it using
|
<a class="reference internal" href="apiref.html#c.nghttp2_submit_request" title="nghttp2_submit_request"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_request()</span></tt></a> function. We can get it using
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_session_get_stream_user_data" title="nghttp2_session_get_stream_user_data"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_get_stream_user_data()</span></tt></a> function. To really sure that
|
<a class="reference internal" href="apiref.html#c.nghttp2_session_get_stream_user_data" title="nghttp2_session_get_stream_user_data"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_get_stream_user_data()</span></tt></a> function. To really sure that
|
||||||
this HEADERS frame is the request HEADERS we have queued, we check
|
this HEADERS frame is the request HEADERS we have queued, we check
|
||||||
that <tt class="docutils literal"><span class="pre">session_data->stream_data</span></tt> and <tt class="docutils literal"><span class="pre">stream_data</span></tt> returned from
|
that <tt class="docutils literal"><span class="pre">session_data->stream_data</span></tt> and <tt class="docutils literal"><span class="pre">stream_data</span></tt> returned from
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_session_get_stream_user_data" title="nghttp2_session_get_stream_user_data"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_get_stream_user_data()</span></tt></a> are pointing the same
|
<a class="reference internal" href="apiref.html#c.nghttp2_session_get_stream_user_data" title="nghttp2_session_get_stream_user_data"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_get_stream_user_data()</span></tt></a> are pointing the same
|
||||||
location. In this example program, we just only uses 1 stream, it is
|
location. In this example program, we just only uses 1 stream, it is
|
||||||
unnecessary to compare them, but real applications surely deal with
|
unnecessary to compare them, but real applications surely deal with
|
||||||
multiple streams, and <em>stream_user_data</em> is very handy to identify
|
multiple streams, and <em>stream_user_data</em> is very handy to identify
|
||||||
|
@ -563,7 +563,7 @@ how to use it here.</p>
|
||||||
</div>
|
</div>
|
||||||
<p>In this tutorial, we are just interested in the HTTP response
|
<p>In this tutorial, we are just interested in the HTTP response
|
||||||
HEADERS. We check te frame type and its category (it should be
|
HEADERS. We check te frame type and its category (it should be
|
||||||
<a class="reference internal" href="apiref.html#NGHTTP2_HCAT_RESPONSE" title="NGHTTP2_HCAT_RESPONSE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_HCAT_RESPONSE</span></tt></a> for HTTP response HEADERS). Also check
|
<a class="reference internal" href="apiref.html#c.NGHTTP2_HCAT_RESPONSE" title="NGHTTP2_HCAT_RESPONSE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_HCAT_RESPONSE</span></tt></a> for HTTP response HEADERS). Also check
|
||||||
its stream ID.</p>
|
its stream ID.</p>
|
||||||
<p>The <tt class="docutils literal"><span class="pre">on_data_chunk_recv_callback()</span></tt> function is invoked when a chunk
|
<p>The <tt class="docutils literal"><span class="pre">on_data_chunk_recv_callback()</span></tt> function is invoked when a chunk
|
||||||
of data is received from the remote peer:</p>
|
of data is received from the remote peer:</p>
|
||||||
|
@ -609,7 +609,7 @@ is about to close:</p>
|
||||||
<p>If the stream ID matches the one we initiated, it means that its
|
<p>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
|
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
|
resource we want (or the stream was reset by RST_STREAM from the
|
||||||
remote peer), we call <a class="reference internal" href="apiref.html#nghttp2_session_terminate_session" title="nghttp2_session_terminate_session"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_terminate_session()</span></tt></a> to
|
remote peer), we call <a class="reference internal" href="apiref.html#c.nghttp2_session_terminate_session" title="nghttp2_session_terminate_session"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_terminate_session()</span></tt></a> to
|
||||||
commencing the closure of the HTTP/2.0 session gracefully. If you have
|
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
|
some data associated for the stream to be closed, you may delete it
|
||||||
here.</p>
|
here.</p>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
||||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||||||
|
@ -22,7 +21,7 @@
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT:'',
|
URL_ROOT:'./',
|
||||||
VERSION:'0.4.0-DEV',
|
VERSION:'0.4.0-DEV',
|
||||||
COLLAPSE_INDEX:false,
|
COLLAPSE_INDEX:false,
|
||||||
FILE_SUFFIX:'.html',
|
FILE_SUFFIX:'.html',
|
||||||
|
@ -157,7 +156,8 @@ repository.</p>
|
||||||
<p>This simple server takes 3 arguments, a port number to listen to, a
|
<p>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
|
path to SSL/TLS private key file and certificate file. Its synopsis
|
||||||
is like this:</p>
|
is like this:</p>
|
||||||
<div class="highlight-c"><pre>$ libevent-server PORT /path/to/server.key /path/to/server.crt</pre>
|
<div class="highlight-c"><div class="highlight"><pre>$ libevent-server PORT /path/to/server.key /path/to/server.crt
|
||||||
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>We use libevent in this tutorial to handle networking I/O. Please
|
<p>We use libevent in this tutorial to handle networking I/O. Please
|
||||||
note that nghttp2 itself does not depend on libevent.</p>
|
note that nghttp2 itself does not depend on libevent.</p>
|
||||||
|
@ -203,7 +203,7 @@ life time:</p>
|
||||||
exactly one byte is used to specify the length of each protocol
|
exactly one byte is used to specify the length of each protocol
|
||||||
identifier. In this tutorial, we advertise the HTTP/2.0 protocol the
|
identifier. In this tutorial, we advertise the HTTP/2.0 protocol the
|
||||||
nghttp2 library supports. The nghttp2 library exports its identifier
|
nghttp2 library supports. The nghttp2 library exports its identifier
|
||||||
in <a class="reference internal" href="apiref.html#NGHTTP2_PROTO_VERSION_ID" title="NGHTTP2_PROTO_VERSION_ID"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_PROTO_VERSION_ID</span></tt></a>. The <tt class="docutils literal"><span class="pre">next_proto_cb()</span></tt> function
|
in <a class="reference internal" href="apiref.html#c.NGHTTP2_PROTO_VERSION_ID" title="NGHTTP2_PROTO_VERSION_ID"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_PROTO_VERSION_ID</span></tt></a>. The <tt class="docutils literal"><span class="pre">next_proto_cb()</span></tt> function
|
||||||
is the server-side NPN callback. In OpenSSL implementation, we just
|
is the server-side NPN callback. In OpenSSL implementation, we just
|
||||||
assign the pointer to the NPN buffers we filled earlier. The NPN
|
assign the pointer to the NPN buffers we filled earlier. The NPN
|
||||||
callback function is set to <tt class="docutils literal"><span class="pre">SSL_CTX</span></tt> object using
|
callback function is set to <tt class="docutils literal"><span class="pre">SSL_CTX</span></tt> object using
|
||||||
|
@ -244,7 +244,7 @@ object in O(1). The first element of this list is pointed by the
|
||||||
is <tt class="docutils literal"><span class="pre">NULL</span></tt>. The <tt class="docutils literal"><span class="pre">handshake_leftlen</span></tt> member of
|
is <tt class="docutils literal"><span class="pre">NULL</span></tt>. The <tt class="docutils literal"><span class="pre">handshake_leftlen</span></tt> member of
|
||||||
<tt class="docutils literal"><span class="pre">http2_session_data</span></tt> is used to track the number of bytes remaining
|
<tt class="docutils literal"><span class="pre">http2_session_data</span></tt> is used to track the number of bytes remaining
|
||||||
when receiving first 24 bytes magic value
|
when receiving first 24 bytes magic value
|
||||||
(<a class="reference internal" href="apiref.html#NGHTTP2_CLIENT_CONNECTION_HEADER" title="NGHTTP2_CLIENT_CONNECTION_HEADER"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_CLIENT_CONNECTION_HEADER</span></tt></a>) from the client. We use
|
(<a class="reference internal" href="apiref.html#c.NGHTTP2_CLIENT_CONNECTION_HEADER" title="NGHTTP2_CLIENT_CONNECTION_HEADER"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_CLIENT_CONNECTION_HEADER</span></tt></a>) from the client. We use
|
||||||
libevent’s bufferevent structure to perform network I/O. Notice that
|
libevent’s bufferevent structure to perform network I/O. Notice that
|
||||||
bufferevent object is in <tt class="docutils literal"><span class="pre">http2_session_data</span></tt> and not in
|
bufferevent object is in <tt class="docutils literal"><span class="pre">http2_session_data</span></tt> and not in
|
||||||
<tt class="docutils literal"><span class="pre">http2_stream_data</span></tt>. This is because <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> is just a
|
<tt class="docutils literal"><span class="pre">http2_stream_data</span></tt>. This is because <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> is just a
|
||||||
|
@ -365,7 +365,7 @@ it:</p>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>We check that the received byte string matches
|
<p>We check that the received byte string matches
|
||||||
<a class="reference internal" href="apiref.html#NGHTTP2_CLIENT_CONNECTION_HEADER" title="NGHTTP2_CLIENT_CONNECTION_HEADER"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_CLIENT_CONNECTION_HEADER</span></tt></a>. When they match, the
|
<a class="reference internal" href="apiref.html#c.NGHTTP2_CLIENT_CONNECTION_HEADER" title="NGHTTP2_CLIENT_CONNECTION_HEADER"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_CLIENT_CONNECTION_HEADER</span></tt></a>. When they match, the
|
||||||
connection state is ready for starting HTTP/2.0 communication. First
|
connection state is ready for starting HTTP/2.0 communication. First
|
||||||
we change the callback functions for the bufferevent object. We use
|
we change the callback functions for the bufferevent object. We use
|
||||||
same <tt class="docutils literal"><span class="pre">eventcb</span></tt> as before. But we specify new <tt class="docutils literal"><span class="pre">readcb</span></tt> and
|
same <tt class="docutils literal"><span class="pre">eventcb</span></tt> as before. But we specify new <tt class="docutils literal"><span class="pre">readcb</span></tt> and
|
||||||
|
@ -387,7 +387,7 @@ these 2 functions later.</p>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>Since we are creating server, nghttp2 session object is created using
|
<p>Since we are creating server, nghttp2 session object is created using
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_session_server_new" title="nghttp2_session_server_new"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_server_new()</span></tt></a> function. We registers 5 callbacks to
|
<a class="reference internal" href="apiref.html#c.nghttp2_session_server_new" title="nghttp2_session_server_new"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_server_new()</span></tt></a> function. We registers 5 callbacks to
|
||||||
nghttp2 session object. We’ll talk about these callbacks later.</p>
|
nghttp2 session object. We’ll talk about these callbacks later.</p>
|
||||||
<p>After initialization of nghttp2 session object, we are going to send
|
<p>After initialization of nghttp2 session object, we are going to send
|
||||||
server connection header in <tt class="docutils literal"><span class="pre">send_server_connection_header()</span></tt>:</p>
|
server connection header in <tt class="docutils literal"><span class="pre">send_server_connection_header()</span></tt>:</p>
|
||||||
|
@ -411,10 +411,10 @@ server connection header in <tt class="docutils literal"><span class="pre">send_
|
||||||
<p>The server connection header is SETTINGS frame. We specify
|
<p>The server connection header is SETTINGS frame. We specify
|
||||||
SETTINGS_MAX_CONCURRENT_STREAMS to 100 in SETTINGS frame. To queue
|
SETTINGS_MAX_CONCURRENT_STREAMS to 100 in SETTINGS frame. To queue
|
||||||
the SETTINGS frame for the transmission, we use
|
the SETTINGS frame for the transmission, we use
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_submit_settings" title="nghttp2_submit_settings"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_settings()</span></tt></a>. Note that <a class="reference internal" href="apiref.html#nghttp2_submit_settings" title="nghttp2_submit_settings"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_settings()</span></tt></a>
|
<a class="reference internal" href="apiref.html#c.nghttp2_submit_settings" title="nghttp2_submit_settings"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_settings()</span></tt></a>. Note that <a class="reference internal" href="apiref.html#c.nghttp2_submit_settings" title="nghttp2_submit_settings"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_settings()</span></tt></a>
|
||||||
function only queues the frame and not actually send it. All
|
function only queues the frame and not actually send it. All
|
||||||
<tt class="docutils literal"><span class="pre">nghttp2_submit_*()</span></tt> family functions have this property. To
|
<tt class="docutils literal"><span class="pre">nghttp2_submit_*()</span></tt> family functions have this property. To
|
||||||
actually send the frame, <a class="reference internal" href="apiref.html#nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> is used, which is
|
actually send the frame, <a class="reference internal" href="apiref.html#c.nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> is used, which is
|
||||||
described about later.</p>
|
described about later.</p>
|
||||||
<p>Since bufferevent may buffer more than first 24 bytes from the client,
|
<p>Since bufferevent may buffer more than first 24 bytes from the client,
|
||||||
we have to process them here since libevent won’t invoke callback
|
we have to process them here since libevent won’t invoke callback
|
||||||
|
@ -440,8 +440,8 @@ functions for these pending data. To process received data, we call
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>In this function, we feed all unprocessed, received data to nghttp2
|
<p>In this function, we feed all unprocessed, received data to nghttp2
|
||||||
session object using <a class="reference internal" href="apiref.html#nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a> function. The
|
session object using <a class="reference internal" href="apiref.html#c.nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a> function. The
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a> processes the received data and may
|
<a class="reference internal" href="apiref.html#c.nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a> processes the received data and may
|
||||||
invoke nghttp2 callbacks and also queue outgoing frames. Since there
|
invoke nghttp2 callbacks and also queue outgoing frames. Since there
|
||||||
may be pending frames, we call <tt class="docutils literal"><span class="pre">session_send()</span></tt> function to send
|
may be pending frames, we call <tt class="docutils literal"><span class="pre">session_send()</span></tt> function to send
|
||||||
those frames. The <tt class="docutils literal"><span class="pre">session_send()</span></tt> function is defined as follows:</p>
|
those frames. The <tt class="docutils literal"><span class="pre">session_send()</span></tt> function is defined as follows:</p>
|
||||||
|
@ -457,10 +457,10 @@ those frames. The <tt class="docutils literal"><span class="pre">session_send()<
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>The <a class="reference internal" href="apiref.html#nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> function serializes the frame into wire
|
<p>The <a class="reference internal" href="apiref.html#c.nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> function serializes the frame into wire
|
||||||
format and call <a class="reference internal" href="apiref.html#nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> with
|
format and call <a class="reference internal" href="apiref.html#c.nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> with
|
||||||
it. We set <tt class="docutils literal"><span class="pre">send_callback()</span></tt> function to
|
it. We set <tt class="docutils literal"><span class="pre">send_callback()</span></tt> function to
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> in
|
<a class="reference internal" href="apiref.html#c.nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> in
|
||||||
<tt class="docutils literal"><span class="pre">initialize_nghttp2_session()</span></tt> function described earlier. It is
|
<tt class="docutils literal"><span class="pre">initialize_nghttp2_session()</span></tt> function described earlier. It is
|
||||||
defined as follows:</p>
|
defined as follows:</p>
|
||||||
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">ssize_t</span> <span class="nf">send_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
|
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">ssize_t</span> <span class="nf">send_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
|
||||||
|
@ -480,19 +480,19 @@ defined as follows:</p>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>Since we use bufferevent to abstract network I/O, we just write the
|
<p>Since we use bufferevent to abstract network I/O, we just write the
|
||||||
data to the bufferevent object. Note that <a class="reference internal" href="apiref.html#nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a>
|
data to the bufferevent object. Note that <a class="reference internal" href="apiref.html#c.nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a>
|
||||||
continues to write all frames queued so far. If we were writing the
|
continues to write all frames queued so far. If we were writing the
|
||||||
data to the non-blocking socket directly using <tt class="docutils literal"><span class="pre">write()</span></tt> system call
|
data to the non-blocking socket directly using <tt class="docutils literal"><span class="pre">write()</span></tt> system call
|
||||||
in the <a class="reference internal" href="apiref.html#nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a>, we will
|
in the <a class="reference internal" href="apiref.html#c.nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a>, we will
|
||||||
surely get <tt class="docutils literal"><span class="pre">EAGAIN</span></tt> or <tt class="docutils literal"><span class="pre">EWOULDBLOCK</span></tt> since the socket has limited
|
surely get <tt class="docutils literal"><span class="pre">EAGAIN</span></tt> or <tt class="docutils literal"><span class="pre">EWOULDBLOCK</span></tt> since the socket has limited
|
||||||
send buffer. If that happens, we can return
|
send buffer. If that happens, we can return
|
||||||
<a class="reference internal" href="apiref.html#NGHTTP2_ERR_WOULDBLOCK" title="NGHTTP2_ERR_WOULDBLOCK"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_WOULDBLOCK</span></tt></a> to signal the nghttp2 library to stop
|
<a class="reference internal" href="apiref.html#c.NGHTTP2_ERR_WOULDBLOCK" title="NGHTTP2_ERR_WOULDBLOCK"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_WOULDBLOCK</span></tt></a> to signal the nghttp2 library to stop
|
||||||
sending further data. But writing to the bufferevent, we have to
|
sending further data. But writing to the bufferevent, we have to
|
||||||
regulate the amount data to be buffered by ourselves to avoid possible
|
regulate the amount data to be buffered by ourselves to avoid possible
|
||||||
huge memory consumption. To achieve this, we check the size of output
|
huge memory consumption. To achieve this, we check the size of output
|
||||||
buffer and if it is more than or equal to
|
buffer and if it is more than or equal to
|
||||||
<tt class="docutils literal"><span class="pre">OUTPUT_WOULDBLOCK_THRESHOLD</span></tt> bytes, we stop writing data and return
|
<tt class="docutils literal"><span class="pre">OUTPUT_WOULDBLOCK_THRESHOLD</span></tt> bytes, we stop writing data and return
|
||||||
<a class="reference internal" href="apiref.html#NGHTTP2_ERR_WOULDBLOCK" title="NGHTTP2_ERR_WOULDBLOCK"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_WOULDBLOCK</span></tt></a> to tell the library to stop calling
|
<a class="reference internal" href="apiref.html#c.NGHTTP2_ERR_WOULDBLOCK" title="NGHTTP2_ERR_WOULDBLOCK"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_WOULDBLOCK</span></tt></a> to tell the library to stop calling
|
||||||
send_callback.</p>
|
send_callback.</p>
|
||||||
<p>The next bufferevent callback is <tt class="docutils literal"><span class="pre">readcb()</span></tt>, which is invoked when
|
<p>The next bufferevent callback is <tt class="docutils literal"><span class="pre">readcb()</span></tt>, which is invoked when
|
||||||
data is available to read in the bufferevent input buffer:</p>
|
data is available to read in the bufferevent input buffer:</p>
|
||||||
|
@ -532,8 +532,8 @@ all data written in the bufferevent output buffer have been sent:</p>
|
||||||
session object keeps track of reception and transmission of GOAWAY
|
session object keeps track of reception and transmission of GOAWAY
|
||||||
frame and other error conditions as well. Using these information,
|
frame and other error conditions as well. Using these information,
|
||||||
nghttp2 session object will tell whether the connection should be
|
nghttp2 session object will tell whether the connection should be
|
||||||
dropped or not. More specifically, both <a class="reference internal" href="apiref.html#nghttp2_session_want_read" title="nghttp2_session_want_read"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_read()</span></tt></a>
|
dropped or not. More specifically, both <a class="reference internal" href="apiref.html#c.nghttp2_session_want_read" title="nghttp2_session_want_read"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_read()</span></tt></a>
|
||||||
and <a class="reference internal" href="apiref.html#nghttp2_session_want_write" title="nghttp2_session_want_write"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_write()</span></tt></a> return 0, we have no business in
|
and <a class="reference internal" href="apiref.html#c.nghttp2_session_want_write" title="nghttp2_session_want_write"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_write()</span></tt></a> return 0, we have no business in
|
||||||
the connection. But since we are using bufferevent and its deferred
|
the connection. But since we are using bufferevent and its deferred
|
||||||
callback option, the bufferevent output buffer may contain the pending
|
callback option, the bufferevent output buffer may contain the pending
|
||||||
data when the <tt class="docutils literal"><span class="pre">writecb()</span></tt> is called. To handle this situation, we
|
data when the <tt class="docutils literal"><span class="pre">writecb()</span></tt> is called. To handle this situation, we
|
||||||
|
@ -641,7 +641,7 @@ fully received:</p>
|
||||||
</div>
|
</div>
|
||||||
<p>First we retrieve <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object associated to the
|
<p>First we retrieve <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object associated to the
|
||||||
stream in <tt class="docutils literal"><span class="pre">on_begin_headers_callback()</span></tt>. It is done using
|
stream in <tt class="docutils literal"><span class="pre">on_begin_headers_callback()</span></tt>. It is done using
|
||||||
<a class="reference internal" href="apiref.html#nghttp2_session_get_stream_user_data" title="nghttp2_session_get_stream_user_data"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_get_stream_user_data()</span></tt></a>. If the requested path cannot
|
<a class="reference internal" href="apiref.html#c.nghttp2_session_get_stream_user_data" title="nghttp2_session_get_stream_user_data"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_get_stream_user_data()</span></tt></a>. If the requested path cannot
|
||||||
be served for some reasons (e.g., file is not found), we send 404
|
be served for some reasons (e.g., file is not found), we send 404
|
||||||
response, which is done in <tt class="docutils literal"><span class="pre">error_reply()</span></tt>. Otherwise, we open
|
response, which is done in <tt class="docutils literal"><span class="pre">error_reply()</span></tt>. Otherwise, we open
|
||||||
requested file and send its content. We send 1 header field
|
requested file and send its content. We send 1 header field
|
||||||
|
@ -664,7 +664,7 @@ requested file and send its content. We send 1 header field
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>The nghttp2 library uses <a class="reference internal" href="apiref.html#nghttp2_data_provider" title="nghttp2_data_provider"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_data_provider</span></tt></a> structure to
|
<p>The nghttp2 library uses <a class="reference internal" href="apiref.html#c.nghttp2_data_provider" title="nghttp2_data_provider"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_data_provider</span></tt></a> structure to
|
||||||
send entity body to the remote peer. The <tt class="docutils literal"><span class="pre">source</span></tt> member of this
|
send entity body to the remote peer. The <tt class="docutils literal"><span class="pre">source</span></tt> member of this
|
||||||
structure is a union and it can be either void pointer or int which is
|
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
|
intended to be used as file descriptor. In this example server, we use
|
||||||
|
@ -689,11 +689,11 @@ function to read content of the file:</p>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>If error happens while reading file, we return
|
<p>If error happens while reading file, we return
|
||||||
<a class="reference internal" href="apiref.html#NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE" title="NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE</span></tt></a>. This tells the library
|
<a class="reference internal" href="apiref.html#c.NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE" title="NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE</span></tt></a>. This tells the library
|
||||||
to send RST_STREAM to the stream. When all data is read, set 1 to
|
to send RST_STREAM to the stream. When all data is read, set 1 to
|
||||||
<tt class="docutils literal"><span class="pre">*eof</span></tt> to tell the nghttp2 library that we have finished reading
|
<tt class="docutils literal"><span class="pre">*eof</span></tt> to tell the nghttp2 library that we have finished reading
|
||||||
file.</p>
|
file.</p>
|
||||||
<p>The <a class="reference internal" href="apiref.html#nghttp2_submit_response" title="nghttp2_submit_response"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_response()</span></tt></a> is used to send response to the remote
|
<p>The <a class="reference internal" href="apiref.html#c.nghttp2_submit_response" title="nghttp2_submit_response"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_submit_response()</span></tt></a> is used to send response to the remote
|
||||||
peer.</p>
|
peer.</p>
|
||||||
<p>The <tt class="docutils literal"><span class="pre">on_stream_close_callback()</span></tt> function is invoked when the stream
|
<p>The <tt class="docutils literal"><span class="pre">on_stream_close_callback()</span></tt> function is invoked when the stream
|
||||||
is about to close:</p>
|
is about to close:</p>
|
||||||
|
|
Loading…
Reference in New Issue