Commit 07b02404 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

Added API reference generator script.

Formatted the public APIs with Sphinx syntax.
parent 1c09a69d
...@@ -20,6 +20,6 @@ ...@@ -20,6 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SUBDIRS = lib examples tests SUBDIRS = lib examples tests doc
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
...@@ -131,6 +131,8 @@ AC_CONFIG_FILES([ ...@@ -131,6 +131,8 @@ AC_CONFIG_FILES([
lib/includes/spdylay/spdylayver.h lib/includes/spdylay/spdylayver.h
tests/Makefile tests/Makefile
examples/Makefile examples/Makefile
doc/Makefile
doc/conf.py
]) ])
AC_OUTPUT AC_OUTPUT
......
apiref.rst
conf.py
manual
# Spdylay - SPDY Library
# Copyright (c) 2012 Tatsuhiro Tsujikawa
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = manual
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
apiref.rst: $(top_builddir)/lib/includes/spdylay/spdylayver.h \
$(top_builddir)/lib/includes/spdylay/spdylay.h
$(builddir)/mkapiref.py --header apiref-header.rst $^ > $@
clean:
-rm apiref.rst
-rm -rf $(BUILDDIR)/*
html: apiref.rst
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Spdylay.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Spdylay.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/Spdylay"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Spdylay"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
Spdylay Documentation
=====================
The documentation of Spdylay is generated using Sphinx. This
directory contains the source files to be processed by Sphinx. The
source file for API reference is generated using a script called
``mkapiref.py`` from the Spdylay C source code.
Generating API reference
------------------------
As described earlier, we use ``mkapiref.py`` to generate rst formatted
text of API reference from C source code. The ``mkapiref.py`` is not
so flexible and it requires that C source code is formatted in rather
strict rules.
To generate API reference, just run ``make html``. It runs
``mkapiref.py`` and then run Sphinx to build the entire document.
The ``mkapiref.py`` reads C source code and searches the comment block
starts with ``/**``. In other words, it only processes the comment
block starting ``/**``. The comment block must end with ``*/``. The
``mkapiref.py`` requires that which type of the object this comment
block refers to. To specify the type of the object, the next line
must contain the so-caled action keyword. Currently, the following
action keywords are supported: ``@function``, ``@functypedef``,
``@enum``, ``@struct`` and ``@union``. The following sections
describes each action keyword.
@function
#########
``@function`` is used to refer to the function. The comment block is
used for the document for the function. After the script sees the end
of the comment block, it consumes the lines as the function
declaration until the line which ends with ``;`` is encountered.
In Sphinx doc, usually the function argument is formatted like
``*this*``. But in C, ``*`` is used for dereferencing a pointer and
we must escape ``*`` with a back slash. To avoid this, we format the
argument like ``|this|``. The ``mkapiref.py`` translates it with
``*this*``, as escaping ``*`` inside ``|`` and ``|`` as necessary.
Note that this shadows the substitution feature of Sphinx.
The example follows::
/**
* @function
*
* Submits PING frame to the |session|.
*/
int spdylay_submit_ping(spdylay_session *session);
@functypedef
############
``@functypedef`` is used to refer to the typedef of the function
pointer. The formatting rule is pretty much the same with
``@function``, but this outputs ``type`` domain, rather than
``function`` domain.
The example follows::
/**
* @functypedef
*
* Callback function invoked when |session| wants to send data to
* remote peer.
*/
typedef ssize_t (*spdylay_send_callback)
(spdylay_session *session,
const uint8_t *data, size_t length, int flags, void *user_data);
@enum
#####
``@enum`` is used to refer to the enum. Currently, only enum typedefs
are supported. The comment block is used for the document for the
enum type itself. To document each values, put comment block starting
with the line ``/**`` and ending with the ``*/`` just before the enum
value. When the line starts with ``}`` is encountered, the
``mkapiref.py`` extracts strings next to ``}`` as the name of enum.
At the time of this writing, Sphinx does not support enum type. So we
use ``type`` domain for enum it self and ``macro`` domain for each
value. To refer to the enum value, use ``:enum:`` pseudo role. The
``mkapiref.py`` replaces it with ``:macro:``. By doing this, when
Sphinx will support enum officially, we can replace ``:enum:`` with
the official role easily.
The example follows::
/**
* @enum
* Error codes used in the Spdylay library.
*/
typedef enum {
/**
* Invalid argument passed.
*/
SPDYLAY_ERR_INVALID_ARGUMENT = -501,
/**
* Zlib error.
*/
SPDYLAY_ERR_ZLIB = -502,
} spdylay_error;
@struct
#######
``@struct`` is used to refer to the struct. Currently, only struct
typedefs are supported. The comment block is used for the document for
the struct type itself.To document each member, put comment block
starting with the line ``/**`` and ending with the ``*/`` just before
the member. When the line starts with ``}`` is encountered, the
``mkapiref.py`` extracts strings next to ``}`` as the name of struct.
The block-less typedef is also supported. In this case, typedef
declaration must be all in one line and the ``mkapiref.py`` uses last
word as the name of struct.
Some examples follow::
/**
* @struct
* The control frame header.
*/
typedef struct {
/**
* SPDY protocol version.
*/
uint16_t version;
/**
* The type of this control frame.
*/
uint16_t type;
/**
* The control frame flags.
*/
uint8_t flags;
/**
* The length field of this control frame.
*/
int32_t length;
} spdylay_ctrl_hd;
/**
* @struct
*
* The primary structure to hold the resources needed for a SPDY
* session. The details of this structure is hidden from the public
* API.
*/
typedef struct spdylay_session spdylay_session;
@union
======
``@union`` is used to refer to the union. Currently, ``@union`` is an
alias of ``@struct``.
API Reference
=============
Includes
--------
To use the public APIs, include ``spdylay/spdylay.h``::
#include <spdylay/spdylay.h>
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Spdylay - SPDY Library
# Copyright (c) 2012 Tatsuhiro Tsujikawa
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# #
# Spdylay documentation build configuration file, created by # Spdylay documentation build configuration file, created by
# sphinx-quickstart on Sun Mar 11 22:57:49 2012. # sphinx-quickstart on Sun Mar 11 22:57:49 2012.
...@@ -48,9 +71,9 @@ copyright = u'2012, Tatsuhiro Tsujikawa' ...@@ -48,9 +71,9 @@ copyright = u'2012, Tatsuhiro Tsujikawa'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '0.1.0' version = '@PACKAGE_VERSION@'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.1.0' release = '@PACKAGE_VERSION@'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
...@@ -64,7 +87,7 @@ release = '0.1.0' ...@@ -64,7 +87,7 @@ release = '0.1.0'
# List of patterns, relative to source directory, that match files and # List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files. # directories to ignore when looking for source files.
exclude_patterns = ['_build'] exclude_patterns = ['manual', 'README.rst', '*-header.rst']
# The reST default role (used for this markup: `text`) to use for all documents. # The reST default role (used for this markup: `text`) to use for all documents.
default_role = 'c:func' default_role = 'c:func'
...@@ -81,6 +104,9 @@ primary_domain = 'c' ...@@ -81,6 +104,9 @@ primary_domain = 'c'
# output. They are ignored by default. # output. They are ignored by default.
#show_authors = False #show_authors = False
# The default language to highlight source code in. The default is 'python'.
highlight_language = 'c'
# The name of the Pygments (syntax highlighting) style to use. # The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx' pygments_style = 'sphinx'
......
...@@ -6,15 +6,20 @@ ...@@ -6,15 +6,20 @@
Welcome to Spdylay's documentation! Welcome to Spdylay's documentation!
=================================== ===================================
This is an experimental implementation of Google's SPDY protocol
version 2 and 3 in C.
This library provides SPDY framing layer implementation. It does not
perform any I/O operations. When the library needs them, it calls the
callback functions provided by the application. It also does not
include any event polling mechanism, so the application can freely
choose the way of handling events. This library code does not depend
on any particular SSL library (except for example programs which
depend on OpenSSL 1.0.1 or later).
Contents: Contents:
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
Indices and tables apiref
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
#!/usr/bin/env python
# Spdylay - SPDY Library
# Copyright (c) 2012 Tatsuhiro Tsujikawa
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Generates API reference from C source code.
import re, sys, argparse
class FunctionDoc:
def __init__(self, name, content, domain):
self.name = name
self.content = content
self.domain = domain
def write(self, out):
print '''.. {}:: {}'''.format(self.domain, self.name)
print ''
for line in self.content:
print ' {}'.format(line)
class StructDoc:
def __init__(self, name, content, members, member_domain):
self.name = name
self.content = content
self.members = members
self.member_domain = member_domain
def write(self, out):
if self.name:
print '''.. type:: {}'''.format(self.name)
print ''
for line in self.content:
print ' {}'.format(line)
print ''
for name, content in self.members:
print ''' .. {}:: {}'''.format(self.member_domain, name)
print ''
for line in content:
print ''' {}'''.format(line)
print ''
class MacroDoc:
def __init__(self, name, content):
self.name = name
self.content = content
def write(self, out):
print '''.. macro:: {}'''.format(self.name)
print ''
for line in self.content:
print ' {}'.format(line)
def make_api_ref(infiles):
macros = []
enums = []
types = []
functions = []
for infile in infiles:
while True:
line = infile.readline()
if not line:
break
elif line == '/**\n':
line = infile.readline()
doctype = line.split()[1]
if doctype == '@function':
functions.append(process_function('function', infile))
elif doctype == '@functypedef':
types.append(process_function('type', infile))
elif doctype == '@struct' or doctype == '@union':
types.append(process_struct(infile))
elif doctype == '@enum':
enums.append(process_enum(infile))
elif doctype == '@macro':
macros.append(process_macro(infile))
alldocs = [('Macros', macros),
('Enums', enums),
('Types (structs, unions and typedefs)', types),
('Functions', functions)]
for title, docs in alldocs:
if not docs:
continue
print title
print '-'*len(title)
for doc in docs:
doc.write(sys.stdout)
print ''
print ''
def process_macro(infile):
content = read_content(infile)
line = infile.readline()
macro_name = line.split()[1]
return MacroDoc(macro_name, content)
def process_enum(infile):
members = []
enum_name = None
content = read_content(infile)
while True:
line = infile.readline()
if not line:
break
elif re.match(r'\s*/\*\*\n', line):
member_content = read_content(infile)
line = infile.readline()
member_name = line.split()[0]
members.append((member_name, member_content))
elif line.startswith('}'):
enum_name = line.rstrip().split()[1]
enum_name = re.sub(r';$', '', enum_name)
break
return StructDoc(enum_name, content, members, 'macro')
def process_struct(infile):
members = []
struct_name = None
content = read_content(infile)
while True:
line = infile.readline()
if not line:
break
elif re.match(r'\s*/\*\*\n', line):
member_content = read_content(infile)
line = infile.readline()
member_name = line.rstrip().rstrip(';')
members.append((member_name, member_content))
elif line.startswith('}') or\
(line.startswith('typedef ') and line.endswith(';\n')):
if line.startswith('}'):
index = 1
else:
index = 3
struct_name = line.rstrip().split()[index]
struct_name = re.sub(r';$', '', struct_name)
break
return StructDoc(struct_name, content, members, 'member')
def process_function(domain, infile):
content = read_content(infile)
func_proto = []
while True:
line = infile.readline()
if not line:
break
elif line == '\n':
break
else:
func_proto.append(line)
func_proto = ''.join(func_proto)
func_proto = re.sub(r';\n$', '', func_proto)
func_proto = re.sub(r'\s+', ' ', func_proto)
return FunctionDoc(func_proto, content, domain)
def read_content(infile):
content = []
while True:
line = infile.readline()
if not line:
break
if re.match(r'\s*\*/\n', line):
break
else:
content.append(transform_content(line.rstrip()))
return content
def arg_repl(matchobj):
return '*{}*'.format(matchobj.group(1).replace('*', '\\*'))
def transform_content(content):
content = re.sub(r'^\s+\* ?', '', content)
content = re.sub(r'\|([^\s|]+)\|', arg_repl, content)
content = re.sub(r':enum:', ':macro:', content)
return content
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Generate API reference")
parser.add_argument('--header', type=argparse.FileType('rb', 0),
help='header inserted at the top of the page')
parser.add_argument('files', nargs='+', type=argparse.FileType('rb', 0),
help='source file')
args = parser.parse_args()
if args.header:
print args.header.read()
for infile in args.files:
make_api_ref(args.files)
...@@ -36,64 +36,126 @@ extern "C" { ...@@ -36,64 +36,126 @@ extern "C" {
#include <spdylay/spdylayver.h> #include <spdylay/spdylayver.h>
struct spdylay_session; struct spdylay_session;
/**
* @struct
*
* The primary structure to hold the resources needed for a SPDY
* session. The details of this structure is hidden from the public
* API.
*/
typedef struct spdylay_session spdylay_session; typedef struct spdylay_session spdylay_session;
/* SPDY protocol version 2 */ /**
* @macro
*
* SPDY protocol version 2
*/
#define SPDYLAY_PROTO_SPDY2 2 #define SPDYLAY_PROTO_SPDY2 2
/* SPDY protocol version 3 */ /**
* @macro
*
* SPDY protocol version 3
*/
#define SPDYLAY_PROTO_SPDY3 3 #define SPDYLAY_PROTO_SPDY3 3
/**
* @enum
*
* Error codes used in the Spdylay library. The following values are
* defined:
*/
typedef enum { typedef enum {
/* Invalid argument passed. */ /**
* Invalid argument passed.
*/
SPDYLAY_ERR_INVALID_ARGUMENT = -501, SPDYLAY_ERR_INVALID_ARGUMENT = -501,
/* Zlib error. */ /**
* Zlib error.
*/
SPDYLAY_ERR_ZLIB = -502, SPDYLAY_ERR_ZLIB = -502,
/* The specified protocol version is not supported. */ /**
* The specified protocol version is not supported.
*/
SPDYLAY_ERR_UNSUPPORTED_VERSION = -503, SPDYLAY_ERR_UNSUPPORTED_VERSION = -503,
/* Used as a return value from spdylay_send_callback and /**
spdylay_recv_callback to indicate that the operation would * Used as a return value from :type:`spdylay_send_callback` and
block. */ * :type:`spdylay_recv_callback` to indicate that the operation
* would block.
*/
SPDYLAY_ERR_WOULDBLOCK = -504, SPDYLAY_ERR_WOULDBLOCK = -504,
/* General protocol error */ /**
* General protocol error
*/
SPDYLAY_ERR_PROTO = -505, SPDYLAY_ERR_PROTO = -505,
/* The frame is invalid. */ /**
* The frame is invalid.
*/
SPDYLAY_ERR_INVALID_FRAME = -506, SPDYLAY_ERR_INVALID_FRAME = -506,
/* The peer performed a shutdown on the connection. */ /**
* The peer performed a shutdown on the connection.
*/
SPDYLAY_ERR_EOF = -507, SPDYLAY_ERR_EOF = -507,
/* Used as a return value from spdylay_data_source_read_callback to /**
indicate that data transfer is postponed. See * Used as a return value from
spdylay_data_source_read_callback for details. */ * :func:`spdylay_data_source_read_callback` to indicate that data
* transfer is postponed. See
* :func:`spdylay_data_source_read_callback` for details.
*/
SPDYLAY_ERR_DEFERRED = -508, SPDYLAY_ERR_DEFERRED = -508,
/* Stream ID has reached maximum value. Therefore no stream ID is /**
available. */ * Stream ID has reached maximum value. Therefore no stream ID is
* available.
*/
SPDYLAY_ERR_STREAM_ID_NOT_AVAILABLE = -509, SPDYLAY_ERR_STREAM_ID_NOT_AVAILABLE = -509,
/* The stream is already closed or it does not exist. */ /**
* The stream is already closed; or the stream ID is invalid.
*/
SPDYLAY_ERR_STREAM_CLOSED = -510, SPDYLAY_ERR_STREAM_CLOSED = -510,
/* RST_STREAM has been queued in outbound queue. The stream is in /**
closing state. */ * RST_STREAM has been queued in outbound queue. The stream is in
* closing state.
*/
SPDYLAY_ERR_STREAM_CLOSING = -511, SPDYLAY_ERR_STREAM_CLOSING = -511,
/* The transmission is not allowed for this stream (e.g., a frame /**
with FIN flag set has already sent) */ * The transmission is not allowed for this stream (e.g., a frame
* with FIN flag set has already sent).
*/
SPDYLAY_ERR_STREAM_SHUT_WR = -512, SPDYLAY_ERR_STREAM_SHUT_WR = -512,
/* The stream ID is invalid. */ /**
* The stream ID is invalid.
*/
SPDYLAY_ERR_INVALID_STREAM_ID = -513, SPDYLAY_ERR_INVALID_STREAM_ID = -513,
/* The state of the stream is not valid (e.g., SYN_REPLY cannot be /**
sent to the stream where SYN_REPLY has been already sent). */ * The state of the stream is not valid (e.g., SYN_REPLY cannot be
* sent to the stream where SYN_REPLY has been already sent).
*/
SPDYLAY_ERR_INVALID_STREAM_STATE = -514, SPDYLAY_ERR_INVALID_STREAM_STATE = -514,
/* Another DATA frame has already been deferred. */ /**
* Another DATA frame has already been deferred.
*/
SPDYLAY_ERR_DEFERRED_DATA_EXIST = -515, SPDYLAY_ERR_DEFERRED_DATA_EXIST = -515,
/* SYN_STREAM is not allowed. (e.g., GOAWAY has been sent and/or /**
received. */ * SYN_STREAM is not allowed. (e.g., GOAWAY has been sent and/or
* received.
*/
SPDYLAY_ERR_SYN_STREAM_NOT_ALLOWED = -516, SPDYLAY_ERR_SYN_STREAM_NOT_ALLOWED = -516,
/* GOAWAY has been already sent. */ /**
* GOAWAY has been already sent.
*/
SPDYLAY_ERR_GOAWAY_ALREADY_SENT = -517, SPDYLAY_ERR_GOAWAY_ALREADY_SENT = -517,
/* The errors < SPDYLAY_ERR_FATAL mean that the library is under /**
unexpected condition that it cannot process any further data * The errors < :enum:`SPDYLAY_ERR_FATAL` mean that the library is
reliably (e.g., out of memory). */ * under unexpected condition that it cannot process any further
* data reliably (e.g., out of memory).
*/
SPDYLAY_ERR_FATAL = -900, SPDYLAY_ERR_FATAL = -900,
/* Out of memory. */ /**
* Out of memory. This is a fatal error.
*/
SPDYLAY_ERR_NOMEM = -901, SPDYLAY_ERR_NOMEM = -901,
/* The user callback function failed. */ /**
* The user callback function failed. This is a fatal error.
*/
SPDYLAY_ERR_CALLBACK_FAILURE = -902, SPDYLAY_ERR_CALLBACK_FAILURE = -902,
} spdylay_error; } spdylay_error;
...@@ -101,165 +163,504 @@ typedef enum { ...@@ -101,165 +163,504 @@ typedef enum {
SPDYLAY_MSG_MORE SPDYLAY_MSG_MORE
} spdylay_io_flag; } spdylay_io_flag;
/**
* @enum
* The frame types in SPDY protocol.
*/
typedef enum { typedef enum {
/**
* The SYN_STREAM control frame.
*/
SPDYLAY_SYN_STREAM = 1, SPDYLAY_SYN_STREAM = 1,
/**
* The SYN_REPLY control frame.
*/
SPDYLAY_SYN_REPLY = 2, SPDYLAY_SYN_REPLY = 2,
/**
* The RST_STREAM control frame.
*/
SPDYLAY_RST_STREAM = 3, SPDYLAY_RST_STREAM = 3,
/**
* The SETTINGS control frame.
*/
SPDYLAY_SETTINGS = 4, SPDYLAY_SETTINGS = 4,
/**
* The NOOP control frame. This is deprecated in SPDY/3.
*/
SPDYLAY_NOOP = 5, SPDYLAY_NOOP = 5,
/**
* The PING control frame.
*/
SPDYLAY_PING = 6, SPDYLAY_PING = 6,
/**
* The GOAWAY control frame.
*/
SPDYLAY_GOAWAY = 7, SPDYLAY_GOAWAY = 7,
/**
* The HEADERS control frame.
*/
SPDYLAY_HEADERS = 8, SPDYLAY_HEADERS = 8,
/* Since SPDY/3 */ /**
* The WINDOW_UPDATE control frame. This was first appeard in
* SPDY/3.
*/
SPDYLAY_WINDOW_UPDATE = 9, SPDYLAY_WINDOW_UPDATE = 9,
/**
* The DATA frame.
*/
SPDYLAY_DATA = 100, SPDYLAY_DATA = 100,
} spdylay_frame_type; } spdylay_frame_type;
/**
* @enum
*
* The flags for a control frame.
*/
typedef enum { typedef enum {
/**
* No flag set.
*/
SPDYLAY_CTRL_FLAG_NONE = 0, SPDYLAY_CTRL_FLAG_NONE = 0,
/**
* FLAG_FIN flag.
*/
SPDYLAY_CTRL_FLAG_FIN = 0x1, SPDYLAY_CTRL_FLAG_FIN = 0x1,
/**
* FLAG_UNIDIRECTIONAL flag.
*/
SPDYLAY_CTRL_FLAG_UNIDIRECTIONAL = 0x2 SPDYLAY_CTRL_FLAG_UNIDIRECTIONAL = 0x2
} spdylay_ctrl_flag; } spdylay_ctrl_flag;
/**
* @enum
* The flags for a DATA frame.
*/
typedef enum { typedef enum {
/**
* No flag set.
*/
SPDYLAY_DATA_FLAG_NONE = 0, SPDYLAY_DATA_FLAG_NONE = 0,
/**
* FLAG_FIN flag.
*/
SPDYLAY_DATA_FLAG_FIN = 0x1 SPDYLAY_DATA_FLAG_FIN = 0x1
} spdylay_data_flag; } spdylay_data_flag;
/**
* @enum
* The flags for the SETTINGS control frame.
*/
typedef enum { typedef enum {
/**
* No flag set.
*/
SPDYLAY_FLAG_SETTINGS_NONE = 0, SPDYLAY_FLAG_SETTINGS_NONE = 0,
/**
* SETTINGS_CLEAR_SETTINGS flag.
*/
SPDYLAY_FLAG_SETTINGS_CLEAR_SETTINGS = 1 SPDYLAY_FLAG_SETTINGS_CLEAR_SETTINGS = 1
} spdylay_settings_flag; } spdylay_settings_flag;
/**
* @enum
* The flags for SETTINGS ID/value pair.
*/
typedef enum { typedef enum {
/**
* No flag set.
*/
SPDYLAY_ID_FLAG_SETTINGS_NONE = 0, SPDYLAY_ID_FLAG_SETTINGS_NONE = 0,
/**
* FLAG_SETTINGS_PERSIST_VALUE flag.
*/
SPDYLAY_ID_FLAG_SETTINGS_PERSIST_VALUE = 1, SPDYLAY_ID_FLAG_SETTINGS_PERSIST_VALUE = 1,
/**
* FLAG_SETTINGS_PERSISTED flag.
*/
SPDYLAY_ID_FLAG_SETTINGS_PERSISTED = 2 SPDYLAY_ID_FLAG_SETTINGS_PERSISTED = 2
} spdylay_settings_id_flag; } spdylay_settings_id_flag;
/**
* @enum
* The SETTINGS ID.
*/
typedef enum { typedef enum {
/**
* SETTINGS_UPLOAD_BANDWIDTH
*/
SPDYLAY_SETTINGS_UPLOAD_BANDWIDTH = 1, SPDYLAY_SETTINGS_UPLOAD_BANDWIDTH = 1,
/**
* SETTINGS_DOWNLOAD_BANDWIDTH
*/
SPDYLAY_SETTINGS_DOWNLOAD_BANDWIDTH = 2, SPDYLAY_SETTINGS_DOWNLOAD_BANDWIDTH = 2,
/**
* SETTINGS_ROUND_TRIP_TIME
*/
SPDYLAY_SETTINGS_ROUND_TRIP_TIME = 3, SPDYLAY_SETTINGS_ROUND_TRIP_TIME = 3,
/**
* SETTINGS_MAX_CONCURRENT_STREAMS
*/
SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS = 4, SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS = 4,
/**
* SETTINGS_CURRENT_CWND
*/
SPDYLAY_SETTINGS_CURRENT_CWND = 5, SPDYLAY_SETTINGS_CURRENT_CWND = 5,
/**
* SETTINGS_DOWNLOAD_RETRANS_RATE
*/
SPDYLAY_SETTINGS_DOWNLOAD_RETRANS_RATE = 6, SPDYLAY_SETTINGS_DOWNLOAD_RETRANS_RATE = 6,
/**
* SETTINGS_INITIAL_WINDOW_SIZE
*/
SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE = 7, SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE = 7,
/* This first appeared in SPDY/3 */ /**
* SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE. This was first appeared
* in SPDY/3.
*/
SPDYLAY_SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8 SPDYLAY_SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8
} spdylay_settings_id; } spdylay_settings_id;
/* Maximum ID of spdylay_settings_id. */ /**
* @macro
* Maximum ID of :type:`spdylay_settings_id`.
*/
#define SPDYLAY_SETTINGS_MAX 8 #define SPDYLAY_SETTINGS_MAX 8
/* Default maximum concurrent streams */ /**
* @macro
* Default maximum concurrent streams.
*/
#define SPDYLAY_INITIAL_MAX_CONCURRENT_STREAMS 100 #define SPDYLAY_INITIAL_MAX_CONCURRENT_STREAMS 100
/* Status code for RST_STREAM */ /**
* @enum
* The status codes for RST_STREAM control frame.
*/
typedef enum { typedef enum {
/* SPDYLAY_OK is not valid status code for RST_STREAM. It is defined /**
just for spdylay library use. */ * SPDYLAY_OK is not valid status code for RST_STREAM. It is defined
* just for spdylay library use.
*/
SPDYLAY_OK = 0, SPDYLAY_OK = 0,
/**
* PROTOCOL_ERROR
*/
SPDYLAY_PROTOCOL_ERROR = 1, SPDYLAY_PROTOCOL_ERROR = 1,
/**
* INVALID_STREAM
*/
SPDYLAY_INVALID_STREAM = 2, SPDYLAY_INVALID_STREAM = 2,
/**
* REFUSED_STREAM
*/
SPDYLAY_REFUSED_STREAM = 3, SPDYLAY_REFUSED_STREAM = 3,
/**
* UNSUPPORTED_VERSION
*/
SPDYLAY_UNSUPPORTED_VERSION = 4, SPDYLAY_UNSUPPORTED_VERSION = 4,
/**
* CANCEL
*/
SPDYLAY_CANCEL = 5, SPDYLAY_CANCEL = 5,
/**
* INTERNAL_ERROR
*/
SPDYLAY_INTERNAL_ERROR = 6, SPDYLAY_INTERNAL_ERROR = 6,
/**
* FLOW_CONTROL_ERROR
*/
SPDYLAY_FLOW_CONTROL_ERROR = 7, SPDYLAY_FLOW_CONTROL_ERROR = 7,
/* Following status codes were introduced in SPDY/3 */ /* Following status codes were introduced in SPDY/3 */
/**
* STREAM_IN_USE
*/
SPDYLAY_STREAM_IN_USE = 8, SPDYLAY_STREAM_IN_USE = 8,
/**
* STREAM_ALREADY_CLOSED
*/
SPDYLAY_STREAM_ALREADY_CLOSED = 9, SPDYLAY_STREAM_ALREADY_CLOSED = 9,
/**
* SPDYLAY_INVALID_CREDENTIALS
*/
SPDYLAY_INVALID_CREDENTIALS = 10, SPDYLAY_INVALID_CREDENTIALS = 10,
/**
* FRAME_TOO_LARGE
*/
FRAME_TOO_LARGE = 11 FRAME_TOO_LARGE = 11
} spdylay_status_code; } spdylay_status_code;
/* Status code for GOAWAY, introduced in SPDY/3 */ /**
* @enum
* The status codes for GOAWAY, introduced in SPDY/3
*/
typedef enum { typedef enum {
/**
* OK. This indicates a normal session teardown.
*/
SPDYLAY_GOAWAY_OK = 0, SPDYLAY_GOAWAY_OK = 0,
/**
* PROTOCOL_ERROR
*/
SPDYLAY_GOAWAY_PROTOCOL_ERROR = 1, SPDYLAY_GOAWAY_PROTOCOL_ERROR = 1,
/**
* INTERNAL_ERROR
*/
SPDYLAY_GOAWAY_INTERNAL_ERROR = 11 SPDYLAY_GOAWAY_INTERNAL_ERROR = 11
} spdylay_goaway_status_code; } spdylay_goaway_status_code;
/**
* @macro
* Lowest priority value in SPDY/2.
*/
#define SPDYLAY_SPDY2_PRI_LOWEST 3 #define SPDYLAY_SPDY2_PRI_LOWEST 3
/**
* @macro
* Lowest priority value in SPDY/3.
*/
#define SPDYLAY_SPDY3_PRI_LOWEST 7 #define SPDYLAY_SPDY3_PRI_LOWEST 7
/**
* @struct
* The control frame header.
*/
typedef struct { typedef struct {
/**
* SPDY protocol version.
*/
uint16_t version; uint16_t version;
/**
* The type of this control frame.
*/
uint16_t type; uint16_t type;
/**
* The control frame flags.
*/
uint8_t flags; uint8_t flags;
/**
* The length field of this control frame.
*/
int32_t length; int32_t length;
} spdylay_ctrl_hd; } spdylay_ctrl_hd;
/**
* @struct
* The SYN_STREAM control frame. It has the following members:
*/
typedef struct { typedef struct {
/**
* The control frame header.
*/
spdylay_ctrl_hd hd; spdylay_ctrl_hd hd;
/**
* The stream ID.
*/
int32_t stream_id; int32_t stream_id;
/**
* The associated-to-stream ID. 0 if this frame has no
* associated-to-stream.
*/
int32_t assoc_stream_id; int32_t assoc_stream_id;
/* 0 (Highest) to SPDYLAY_SPDY2_PRI_LOWEST or /**
SPDYLAY_SPDY3_PRI_LOWEST (lowest), depending on the protocol * The priority of this frame. 0 (Highest) to
version. */ * :macro:`SPDYLAY_SPDY2_PRI_LOWEST` or
* :macro:`SPDYLAY_SPDY3_PRI_LOWEST` (lowest), depending on the
* protocol version.
*/
uint8_t pri; uint8_t pri;
/* Since SPDY/3 */ /**
* The index in server's CREDENTIAL vector of the client certificate.
* This was introduced in SPDY/3.
*/
uint8_t slot; uint8_t slot;
/**
* The name/value pairs. For i > 0, ``nv[2*i]`` contains a pointer
* to the name string and ``nv[2*i+1]`` contains a pointer to the
* value string. The one beyond last value must be ``NULL``. That
* is, if the |nv| contains N name/value pairs, ``nv[2*N]`` must be
* ``NULL``.
*/
char **nv; char **nv;
} spdylay_syn_stream; } spdylay_syn_stream;
/**
* @struct
* The SYN_REPLY control frame. It has the following members:
*/
typedef struct { typedef struct {
/**
* The control frame header.
*/
spdylay_ctrl_hd hd; spdylay_ctrl_hd hd;
/**
* The stream ID.
*/
int32_t stream_id; int32_t stream_id;
/**
* The name/value pairs. For i > 0, ``nv[2*i]`` contains a pointer
* to the name string and ``nv[2*i+1]`` contains a pointer to the
* value string. The one beyond last value must be ``NULL``. That
* is, if the |nv| contains N name/value pairs, ``nv[2*N]`` must be
* ``NULL``.
*/
char **nv; char **nv;
} spdylay_syn_reply; } spdylay_syn_reply;
/**
* @struct
* The HEADERS control frame. It has the following members:
*/
typedef struct { typedef struct {
/**
* The control frame header.
*/
spdylay_ctrl_hd hd; spdylay_ctrl_hd hd;
/**
* The stream ID.
*/
int32_t stream_id; int32_t stream_id;
/**
* The name/value pairs. For i > 0, ``nv[2*i]`` contains a pointer
* to the name string and ``nv[2*i+1]`` contains a pointer to the
* value string. The one beyond last value must be ``NULL``. That
* is, if the |nv| contains N name/value pairs, ``nv[2*N]`` must be
* ``NULL``.
*/
char **nv; char **nv;
} spdylay_headers; } spdylay_headers;
/**
* @struct
* The RST_STREAM control frame. It has the following members:
*/
typedef struct { typedef struct {
/**
* The control frame header.
*/
spdylay_ctrl_hd hd; spdylay_ctrl_hd hd;
/**
* The stream ID.
*/
int32_t stream_id; int32_t stream_id;
/**
* The status code. See :type:`spdylay_status_code`.
*/
uint32_t status_code; uint32_t status_code;
} spdylay_rst_stream; } spdylay_rst_stream;
/**
* @struct
* The SETTINGS ID/Value pair. It has the following members:
*/
typedef struct { typedef struct {
/**
* The SETTINGS ID. See :type:`spdylay_settings_id`.
*/
int32_t settings_id; int32_t settings_id;
/**
* The flags. See :type:`spdylay_settings_id_flag`.
*/
uint8_t flags; uint8_t flags;
/**
* The value of this entry.
*/
uint32_t value; uint32_t value;
} spdylay_settings_entry; } spdylay_settings_entry;
/**
* @struct
* The SETTINGS control frame. It has the following members:
*/
typedef struct { typedef struct {
/**
* The control frame header.
*/
spdylay_ctrl_hd hd; spdylay_ctrl_hd hd;
/* Number of entries in |iv| */ /**
* The number of SETTINGS ID/Value pairs in |iv|.
*/
size_t niv; size_t niv;
/**
* The pointer to the array of SETTINGS ID/Value pair.
*/
spdylay_settings_entry *iv; spdylay_settings_entry *iv;
} spdylay_settings; } spdylay_settings;
/**
* @struct
* The PING control frame. It has the following members:
*/
typedef struct { typedef struct {
/**
* The control frame header.
*/
spdylay_ctrl_hd hd; spdylay_ctrl_hd hd;
/**
* The unique ID.
*/
uint32_t unique_id; uint32_t unique_id;
} spdylay_ping; } spdylay_ping;
/**
* @struct
* The GOAWAY control frame. It has the following members:
*/
typedef struct { typedef struct {
/**
* The control frame header.
*/
spdylay_ctrl_hd hd; spdylay_ctrl_hd hd;
/**
* The last-good-stream ID.
*/
int32_t last_good_stream_id; int32_t last_good_stream_id;
/* Since SPDY/3 */ /**
* The status code. It was introduced in SPDY/3. See
* :type:`spdylay_goaway_status_code`.
*/
uint32_t status_code; uint32_t status_code;
} spdylay_goaway; } spdylay_goaway;
/* WINDOW_UPDATE is introduced since SPDY/3 */ /**
* @struct
*
* The WINDOW_UPDATE control frame. It was introduced in SPDY/3. It
* has the following members:
*/
typedef struct { typedef struct {
/**
* The control frame header.
*/
spdylay_ctrl_hd hd; spdylay_ctrl_hd hd;
/**
* The stream ID.
*/
int32_t stream_id; int32_t stream_id;
/**
* The delta-window-size.
*/
int32_t delta_window_size; int32_t delta_window_size;
} spdylay_window_update; } spdylay_window_update;
/**
* @union
*
* This union represents the some kind of data source passed to
* :type:`spdylay_data_source_read_callback`.
*/
typedef union { typedef union {
/**
* The integer field, suitable for a file descriptor.
*/
int fd; int fd;
/**
* The pointer to an arbitrary object.
*/
void *ptr; void *ptr;
} spdylay_data_source; } spdylay_data_source;
/* /**
* @functypedef
*
* Callback function invoked when the library wants to read data from * Callback function invoked when the library wants to read data from
* |source|. The read data is sent in the stream |stream_id|. The * |source|. The read data is sent in the stream |stream_id|. The
* implementation of this function must read at most |length| bytes of * implementation of this function must read at most |length| bytes of
...@@ -267,175 +668,316 @@ typedef union { ...@@ -267,175 +668,316 @@ typedef union {
* |buf| and return number of data stored in |buf|. If EOF is reached, * |buf| and return number of data stored in |buf|. If EOF is reached,
* set |*eof| to 1. If the application wants to postpone DATA frames, * set |*eof| to 1. If the application wants to postpone DATA frames,
* (e.g., asynchronous I/O, or reading data blocks for long time), it * (e.g., asynchronous I/O, or reading data blocks for long time), it
* is achieved by returning SPDYLAY_ERR_DEFERRED without reading any * is achieved by returning :enum:`SPDYLAY_ERR_DEFERRED` without
* data in this invocation. The library removes DATA frame from * reading any data in this invocation. The library removes DATA
* outgoing queue temporarily. To move back deferred DATA frame to * frame from the outgoing queue temporarily. To move back deferred
* outgoing queue, call spdylay_session_resume_data(). In case of * DATA frame to outgoing queue, call `spdylay_session_resume_data()`.
* error, return SPDYLAY_ERR_CALLBACK_FAILURE, which leads to session * In case of error, return :enum:`SPDYLAY_ERR_CALLBACK_FAILURE`,
* failure. * which leads to session failure.
*/ */
typedef ssize_t (*spdylay_data_source_read_callback) typedef ssize_t (*spdylay_data_source_read_callback)
(spdylay_session *session, int32_t stream_id, (spdylay_session *session, int32_t stream_id,
uint8_t *buf, size_t length, int *eof, uint8_t *buf, size_t length, int *eof,
spdylay_data_source *source, void *user_data); spdylay_data_source *source, void *user_data);
/**
* @struct
*
* This struct represents the data source and the way to read a chunk
* of data from it.
*/
typedef struct { typedef struct {
/**
* The data source.
*/
spdylay_data_source source; spdylay_data_source source;
/**
* The callback function to read a chunk of data from |source|.
*/
spdylay_data_source_read_callback read_callback; spdylay_data_source_read_callback read_callback;
} spdylay_data_provider; } spdylay_data_provider;
/**
* @struct
* The DATA frame. It has the following members:
*/
typedef struct { typedef struct {
/**
* The stream ID.
*/
int32_t stream_id; int32_t stream_id;
/**
* The DATA frame flags. See :type:`spdylay_data_flag`.
*/
uint8_t flags; uint8_t flags;
/* Initially eof is 0. It becomes 1 if all data are read. */ /**
* The flag to indicate whether EOF was reached or not. Initially
* |eof| is 0. It becomes 1 after all data were read.
*/
uint8_t eof; uint8_t eof;
/**
* The data to be sent for this DATA frame.
*/
spdylay_data_provider data_prd; spdylay_data_provider data_prd;
} spdylay_data; } spdylay_data;
/**
* @union
*
* This union includes all control frames and DATA frame to pass them
* to various function calls as spdylay_frame type.
*/
typedef union { typedef union {
/**
* The SYN_STREAM control frame.
*/
spdylay_syn_stream syn_stream; spdylay_syn_stream syn_stream;
/**
* The SYN_REPLY control frame.
*/
spdylay_syn_reply syn_reply; spdylay_syn_reply syn_reply;
/**
* The RST_STREAM control frame.
*/
spdylay_rst_stream rst_stream; spdylay_rst_stream rst_stream;
/**
* The SETTINGS control frame.
*/
spdylay_settings settings; spdylay_settings settings;
/**
* The PING control frame.
*/
spdylay_ping ping; spdylay_ping ping;
/**
* The GOAWAY control frame.
*/
spdylay_goaway goaway; spdylay_goaway goaway;
/**
* The HEADERS control frame.
*/
spdylay_headers headers; spdylay_headers headers;
/* Since SPDY/3 */ /**
* The WINDOW_UPDATE control frame.
*/
spdylay_window_update window_update; spdylay_window_update window_update;
/**
* The DATA frame.
*/
spdylay_data data; spdylay_data data;
} spdylay_frame; } spdylay_frame;
/* /**
* Callback function invoked when |session| want to send data to * @functypedef
*
* Callback function invoked when |session| wants to send data to the
* remote peer. The implementation of this function must send at most * remote peer. The implementation of this function must send at most
* |length| bytes of data stored in |data|. It must return the number * |length| bytes of data stored in |data|. It must return the number
* of bytes sent if it succeeds. If it cannot send any single byte * of bytes sent if it succeeds. If it cannot send any single byte
* without blocking, it must return SPDYLAY_ERR_WOULDBLOCK. For other * without blocking, it must return
* errors, it must return SPDYLAY_ERR_CALLBACK_FAILURE. * :enum:`SPDYLAY_ERR_WOULDBLOCK`. For other errors, it must return
* :enum:`SPDYLAY_ERR_CALLBACK_FAILURE`.
*/ */
typedef ssize_t (*spdylay_send_callback) typedef ssize_t (*spdylay_send_callback)
(spdylay_session *session, (spdylay_session *session,
const uint8_t *data, size_t length, int flags, void *user_data); const uint8_t *data, size_t length, int flags, void *user_data);
/* /**
* Callback function invoked when |session| want to receive data from * @functypedef
* remote peer. The implementation of this function must read at most *
* |length| bytes of data and store it in |buf|. It must return the * Callback function invoked when |session| wants to receive data from
* number of bytes written in |buf| if it succeeds. If it cannot read * the remote peer. The implementation of this function must read at
* any single byte without blocking, it must return * most |length| bytes of data and store it in |buf|. It must return
* SPDYLAY_ERR_WOULDBLOCK. If it gets EOF before it reads any single * the number of bytes written in |buf| if it succeeds. If it cannot
* byte, it must return SPDYLAY_ERR_EOF. For other errors, it must * read any single byte without blocking, it must return
* return SPDYLAY_ERR_CALLBACK_FAILURE. * :enum:`SPDYLAY_ERR_WOULDBLOCK`. If it gets EOF before it reads any
* single byte, it must return :enum:`SPDYLAY_ERR_EOF`. For other
* errors, it must return :enum:`SPDYLAY_ERR_CALLBACK_FAILURE`.
*/ */
typedef ssize_t (*spdylay_recv_callback) typedef ssize_t (*spdylay_recv_callback)
(spdylay_session *session, (spdylay_session *session,
uint8_t *buf, size_t length, int flags, void *user_data); uint8_t *buf, size_t length, int flags, void *user_data);
/* /**
* Callback function invoked by spdylay_session_recv() when a control * @functypedef
* frame is arrived. *
* Callback function invoked by `spdylay_session_recv()` when a
* control frame is arrived.
*/ */
typedef void (*spdylay_on_ctrl_recv_callback) typedef void (*spdylay_on_ctrl_recv_callback)
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, (spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
void *user_data); void *user_data);
/* /**
* Callback function invoked by spdylay_session_recv() when an invalid * @functypedef
* control frame is arrived, which typically the case where RST_STREAM *
* will be sent * Callback function invoked by `spdylay_session_recv()` when an
* invalid control frame is arrived. When this callback function is
* invoked, either RST_STREAM or GOAWAY will be sent.
*/ */
typedef void (*spdylay_on_invalid_ctrl_recv_callback) typedef void (*spdylay_on_invalid_ctrl_recv_callback)
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, (spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
void *user_data); void *user_data);
/* /**
* Callback function invoked when data chunk of DATA frame is * @functypedef
* received. |stream_id| is the stream ID of this DATA frame belongs *
* to. |flags| is the flags of DATA frame which this data chunk is * Callback function invoked when a chunk of data in DATA frame is
* contained. flags & SPDYLAY_DATA_FLAG_FIN does not necessarily mean * received. The |stream_id| is the stream ID of this DATA frame
* this chunk of data is the last one in the stream. You should use * belongs to. The |flags| is the flags of DATA frame which this data
* spdylay_on_data_recv_callback to know all data frames are received. * chunk is contained. ``(flags & SPDYLAY_DATA_FLAG_FIN) != 0`` does
* not necessarily mean this chunk of data is the last one in the
* stream. You should use :type:`spdylay_on_data_recv_callback` to
* know all data frames are received.
*/ */
typedef void (*spdylay_on_data_chunk_recv_callback) typedef void (*spdylay_on_data_chunk_recv_callback)
(spdylay_session *session, uint8_t flags, int32_t stream_id, (spdylay_session *session, uint8_t flags, int32_t stream_id,
const uint8_t *data, size_t len, void *user_data); const uint8_t *data, size_t len, void *user_data);
/* /**
* @functypedef
*
* Callback function invoked when DATA frame is received. The actual * Callback function invoked when DATA frame is received. The actual
* data it contains are received by spdylay_on_data_recv_callback. * data it contains are received by
* :type:`spdylay_on_data_chunk_recv_callback`.
*/ */
typedef void (*spdylay_on_data_recv_callback) typedef void (*spdylay_on_data_recv_callback)
(spdylay_session *session, uint8_t flags, int32_t stream_id, int32_t length, (spdylay_session *session, uint8_t flags, int32_t stream_id, int32_t length,
void *user_data); void *user_data);
/* /**
* Callback function invoked after frame |frame| of type |type| is * @functypedef
* sent. *
* Callback function invoked before the control frame |frame| of type
* |type| is sent. This may be useful, for example, to know the stream
* ID of SYN_STREAM frame (see also
* `spdylay_session_get_stream_user_data()`), which is not assigned
* when it was queued.
*/
typedef void (*spdylay_before_ctrl_send_callback)
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
void *user_data);
/**
* @functypedef
*
* Callback function invoked after the control frame |frame| of type
* |type| is sent.
*/ */
typedef void (*spdylay_on_ctrl_send_callback) typedef void (*spdylay_on_ctrl_send_callback)
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, (spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
void *user_data); void *user_data);
/* /**
* @functypedef
*
* Callback function invoked after the control frame |frame| of type * Callback function invoked after the control frame |frame| of type
* |type| is not sent because of the error. The error is indicated by * |type| is not sent because of the error. The error is indicated by
* the |error|, which is one of the values defined in spdylay_error. * the |error|, which is one of the values defined in
* :type:`spdylay_error`.
*/ */
typedef void (*spdylay_on_ctrl_not_send_callback) typedef void (*spdylay_on_ctrl_not_send_callback)
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, (spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
int error, void *user_data); int error, void *user_data);
/* /**
* @functypedef
*
* Callback function invoked after DATA frame is sent. * Callback function invoked after DATA frame is sent.
*/ */
typedef void (*spdylay_on_data_send_callback) typedef void (*spdylay_on_data_send_callback)
(spdylay_session *session, uint8_t flags, int32_t stream_id, int32_t length, (spdylay_session *session, uint8_t flags, int32_t stream_id, int32_t length,
void *user_data); void *user_data);
/* /**
* Callback function invoked before frame |frame| of type |type| is * @functypedef
* sent. This may be useful, for example, to know the stream ID of *
* SYN_STREAM frame (see also spdylay_session_get_stream_user_data), * Callback function invoked when the stream |stream_id| is
* which is not assigned when it was queued. * closed. The reason of closure is indicated by the
*/ * |status_code|. The stream_user_data, which was specified in
typedef void (*spdylay_before_ctrl_send_callback) * `spdylay_submit_request()` or `spdylay_submit_syn_stream()`, is
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, * still available in this function.
void *user_data);
/*
* Callback function invoked when stream |stream_id| is closed. The
* reason of closure is indicated by |status_code|. stream_user_data
* is still available in this function.
*/ */
typedef void (*spdylay_on_stream_close_callback) typedef void (*spdylay_on_stream_close_callback)
(spdylay_session *session, int32_t stream_id, spdylay_status_code status_code, (spdylay_session *session, int32_t stream_id, spdylay_status_code status_code,
void *user_data); void *user_data);
/* /**
* Callback function invoked when request from remote peer is * @functypedef
* received. In other words, frame with FIN flag set is received. In *
* HTTP, this means HTTP request, including request body, is fully * Callback function invoked when request from the remote peer is
* received. In other words, the frame with FIN flag set is received.
* In HTTP, this means HTTP request, including request body, is fully
* received. * received.
*/ */
typedef void (*spdylay_on_request_recv_callback) typedef void (*spdylay_on_request_recv_callback)
(spdylay_session *session, int32_t stream_id, void *user_data); (spdylay_session *session, int32_t stream_id, void *user_data);
/**
* @struct
*
* Callback functions.
*/
typedef struct { typedef struct {
/**
* Callback function invoked when |session| wants to send data to
* the remote peer.
*/
spdylay_send_callback send_callback; spdylay_send_callback send_callback;
/**
* Callback function invoked when |session| wants to receive data
* from the remote peer.
*/
spdylay_recv_callback recv_callback; spdylay_recv_callback recv_callback;
/**
* Callback function invoked by `spdylay_session_recv()` when a
* control frame is arrived.
*/
spdylay_on_ctrl_recv_callback on_ctrl_recv_callback; spdylay_on_ctrl_recv_callback on_ctrl_recv_callback;
/**
* Callback function invoked by `spdylay_session_recv()` when an
* invalid control frame is arrived.
*/
spdylay_on_invalid_ctrl_recv_callback on_invalid_ctrl_recv_callback; spdylay_on_invalid_ctrl_recv_callback on_invalid_ctrl_recv_callback;
/**
* Callback function invoked when a chunk of data in DATA frame is
* received.
*/
spdylay_on_data_chunk_recv_callback on_data_chunk_recv_callback; spdylay_on_data_chunk_recv_callback on_data_chunk_recv_callback;
/**
* Callback function invoked when DATA frame is received.
*/
spdylay_on_data_recv_callback on_data_recv_callback; spdylay_on_data_recv_callback on_data_recv_callback;
/**
* Callback function invoked before the control frame is sent.
*/
spdylay_before_ctrl_send_callback before_ctrl_send_callback; spdylay_before_ctrl_send_callback before_ctrl_send_callback;
/**
* Callback function invoked after the control frame is sent.
*/
spdylay_on_ctrl_send_callback on_ctrl_send_callback; spdylay_on_ctrl_send_callback on_ctrl_send_callback;
/**
* The callback function invoked when a control frame is not sent
* because of an error.
*/
spdylay_on_ctrl_not_send_callback on_ctrl_not_send_callback; spdylay_on_ctrl_not_send_callback on_ctrl_not_send_callback;
/**
* Callback function invoked after DATA frame is sent.
*/
spdylay_on_data_send_callback on_data_send_callback; spdylay_on_data_send_callback on_data_send_callback;
/**
* Callback function invoked when the stream is closed.
*/
spdylay_on_stream_close_callback on_stream_close_callback; spdylay_on_stream_close_callback on_stream_close_callback;
/**
* Callback function invoked when request from the remote peer is
* received.
*/
spdylay_on_request_recv_callback on_request_recv_callback; spdylay_on_request_recv_callback on_request_recv_callback;
} spdylay_session_callbacks; } spdylay_session_callbacks;
/* /**
* @function
*
* Initializes |*session_ptr| for client use, using the protocol * Initializes |*session_ptr| for client use, using the protocol
* version |version|. The all members of |callbacks| are copied to * version |version|. The all members of |callbacks| are copied to
* |*session_ptr|. Therefore |*session_ptr| does not store * |*session_ptr|. Therefore |*session_ptr| does not store
...@@ -445,11 +987,11 @@ typedef struct { ...@@ -445,11 +987,11 @@ typedef struct {
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
* SPDYLAY_ERR_ZLIB * :enum:`SPDYLAY_ERR_ZLIB`
* The z_stream initialization failed. * The z_stream initialization failed.
* SPDYLAY_ERR_UNSUPPORTED_VERSION * :enum:`SPDYLAY_ERR_UNSUPPORTED_VERSION`
* The version is not supported. * The version is not supported.
*/ */
int spdylay_session_client_new(spdylay_session **session_ptr, int spdylay_session_client_new(spdylay_session **session_ptr,
...@@ -457,7 +999,9 @@ int spdylay_session_client_new(spdylay_session **session_ptr, ...@@ -457,7 +999,9 @@ int spdylay_session_client_new(spdylay_session **session_ptr,
const spdylay_session_callbacks *callbacks, const spdylay_session_callbacks *callbacks,
void *user_data); void *user_data);
/* /**
* @function
*
* Initializes |*session_ptr| for server use, using the protocol * Initializes |*session_ptr| for server use, using the protocol
* version |version|. The all members of |callbacks| are copied to * version |version|. The all members of |callbacks| are copied to
* |*session_ptr|. Therefore |*session_ptr| does not store * |*session_ptr|. Therefore |*session_ptr| does not store
...@@ -467,11 +1011,11 @@ int spdylay_session_client_new(spdylay_session **session_ptr, ...@@ -467,11 +1011,11 @@ int spdylay_session_client_new(spdylay_session **session_ptr,
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
* SPDYLAY_ERR_ZLIB * :enum:`SPDYLAY_ERR_ZLIB`
* The z_stream initialization failed. * The z_stream initialization failed.
* SPDYLAY_ERR_UNSUPPORTED_VERSION * :enum:`SPDYLAY_ERR_UNSUPPORTED_VERSION`
* The version is not supported. * The version is not supported.
*/ */
int spdylay_session_server_new(spdylay_session **session_ptr, int spdylay_session_server_new(spdylay_session **session_ptr,
...@@ -479,141 +1023,190 @@ int spdylay_session_server_new(spdylay_session **session_ptr, ...@@ -479,141 +1023,190 @@ int spdylay_session_server_new(spdylay_session **session_ptr,
const spdylay_session_callbacks *callbacks, const spdylay_session_callbacks *callbacks,
void *user_data); void *user_data);
/* /**
* Frees any resources allocated for |session|. * @function
*
* Frees any resources allocated for |session|. If |session| is
* ``NULL``, this function does nothing.
*/ */
void spdylay_session_del(spdylay_session *session); void spdylay_session_del(spdylay_session *session);
/* /**
* @function
*
* Sends pending frames to the remote peer. * Sends pending frames to the remote peer.
* *
* This function retrieves the highest prioritized frame from the * This function retrieves the highest prioritized frame from the
* outbound queue and sends it to the remote peer. It does this as * outbound queue and sends it to the remote peer. It does this as
* many as possible until the user callback send_callback returns * many as possible until the user callback
* SPDYLAY_ERR_WOULDBLOCK or the outbound queue becomes empty. This * :member:`spdylay_session_callbacks.send_callback` returns
* function calls several callback functions which are passed when * :enum:`SPDYLAY_ERR_WOULDBLOCK` or the outbound queue becomes empty.
* initializing the |session|. Here is the simple time chart which * This function calls several callback functions which are passed
* tells when each callback is invoked: * when initializing the |session|. Here is the simple time chart
* which tells when each callback is invoked:
* *
* 1. Get the next frame to send from outbound queue. * 1. Get the next frame to send from outbound queue.
* 2. Prepare transmission of the frame. * 2. Prepare transmission of the frame.
* 3. If the control frame cannot be sent because some preconditions * 3. If the control frame cannot be sent because some preconditions
* are not met (e.g., SYN_STREAM cannot be sent after GOAWAY), * are not met (e.g., SYN_STREAM cannot be sent after GOAWAY),
* on_ctrl_not_send_callback is invoked. Skip following steps. * :member:`spdylay_session_callbacks.on_ctrl_not_send_callback` is
* invoked. Skip following steps.
* 4. If the frame is SYN_STREAM, the stream is opened here. * 4. If the frame is SYN_STREAM, the stream is opened here.
* 5. before_ctrl_send_callback is invoked. * 5. :member:`spdylay_session_callbacks.before_ctrl_send_callback` is
* 6. send_callback is invoked one or more times (while the frame is * invoked.
* completely sent). * 6. :member:`spdylay_session_callbacks.send_callback` is invoked one
* 7. If the frame is a control frame, on_ctrl_send_callback is invoked. * or more times (while the frame is completely sent).
* 8. If the frame is a DATA frame, on_data_send_callback is invoked. * 7. If the frame is a control frame,
* :member:`spdylay_session_callbacks.on_ctrl_send_callback` is
* invoked.
* 8. If the frame is a DATA frame,
* :member:`spdylay_session_callbacks.on_data_send_callback` is
* invoked.
* 9. If the transmission of the frame triggers closure of the stream, * 9. If the transmission of the frame triggers closure of the stream,
* the stream is closed and on_stream_close_callback is invoked. * the stream is closed and
* :member:`spdylay_session_callbacks.on_stream_close_callback` is
* invoked.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
* SPDYLAY_ERR_CALLBACK_FAILURE * :enum:`SPDYLAY_ERR_CALLBACK_FAILURE`
* The callback function failed. * The callback function failed.
*/ */
int spdylay_session_send(spdylay_session *session); int spdylay_session_send(spdylay_session *session);
/* /**
* @function
*
* Receives frames from the remote peer. * Receives frames from the remote peer.
* *
* This function receives as many frames as possible until the user * This function receives as many frames as possible until the user
* callback recv_callback returns SPDYLAY_ERR_WOULDBLOCK. This * callback :member:`spdylay_session_callbacks.recv_callback` returns
* function calls several callback functions which are passed when * :enum:`SPDYLAY_ERR_WOULDBLOCK`. This function calls several
* initializing the |session|. Here is the simple time chart which * callback functions which are passed when initializing the
* tells when each callback is invoked: * |session|. Here is the simple time chart which tells when each
* * callback is invoked:
* 1. recv_callback is invoked one or more times to receive frame header. *
* 1. :member:`spdylay_session_callbacks.recv_callback` is invoked one
* or more times to receive frame header.
* 2. If the frame is DATA frame: * 2. If the frame is DATA frame:
* 2.1. recv_callback is invoked to receive DATA payload. For each *
* chunk of data, on_data_chunk_recv_callback is invoked. * 2.1. :member:`spdylay_session_callbacks.recv_callback` is invoked
* 2.2. If one DATA frame is completely received, on_data_recv_callback * to receive DATA payload. For each chunk of data,
* :member:`spdylay_session_callbacks.on_data_chunk_recv_callback`
* is invoked.
* 2.2. If one DATA frame is completely received,
* :member:`spdylay_session_callbacks.on_data_recv_callback` is
* invoked. If the frame is the final frame of the request,
* :member:`spdylay_session_callbacks.on_request_recv_callback`
* is invoked. If the reception of the frame triggers the
* closure of the stream,
* :member:`spdylay_session_callbacks.on_stream_close_callback`
* is invoked. * is invoked.
* If the frame is the final frame of the request, *
* on_request_recv_callback is invoked.
* If the reception of the frame triggers the closure of the stream,
* on_stream_close_callback is invoked.
* 3. If the frame is the control frame: * 3. If the frame is the control frame:
* 3.1. recv_callback is invoked one or more times to receive whole frame. *
* 3.2. If the received frame is valid, on_ctrl_recv_callback is invoked. * 3.1. :member:`spdylay_session_callbacks.recv_callback` is invoked
* If the frame is the final frame of the request, * one or more times to receive whole frame.
* on_request_recv_callback is invoked. * 3.2. If the received frame is valid,
* If the reception of the frame triggers the closure of the stream, * :member:`spdylay_session_callbacks.on_ctrl_recv_callback` is
* on_stream_close_callback is invoked. * invoked. If the frame is the final frame of the request,
* 3.3. If the received frame is unpacked but is interpreted as invalid, * :member:`spdylay_session_callbacks.on_request_recv_callback`
* on_invalid_ctrl_recv_callback is invoked. * is invoked. If the reception of the frame triggers the
* closure of the stream,
* :member:`spdylay_session_callbacks.on_stream_close_callback`
* is invoked.
* 3.3. If the received frame is unpacked but is interpreted as
* invalid,
* :member:`spdylay_session_callbacks.on_invalid_ctrl_recv_callback`
* is invoked.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_EOF * :enum:`SPDYLAY_ERR_EOF`
* The remote peer did shutdown on the connection. * The remote peer did shutdown on the connection.
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
* SPDYLAY_ERR_CALLBACK_FAILURE * :enum:`SPDYLAY_ERR_CALLBACK_FAILURE`
* The callback function failed. * The callback function failed.
*/ */
int spdylay_session_recv(spdylay_session *session); int spdylay_session_recv(spdylay_session *session);
/* /**
* Put back previously deferred DATA frame in the stream |stream_id| * @function
* to outbound queue. *
* Puts back previously deferred DATA frame in the stream |stream_id|
* to the outbound queue.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_INVALID_ARGUMENT * :enum:`SPDYLAY_ERR_INVALID_ARGUMENT`
* The stream does not exist or no deferred data exist. * The stream does not exist or no deferred data exist.
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
int spdylay_session_resume_data(spdylay_session *session, int32_t stream_id); int spdylay_session_resume_data(spdylay_session *session, int32_t stream_id);
/* /**
* Returns nonzero value if |session| want to receive data from the * @function
*
* Returns nonzero value if |session| wants to receive data from the
* remote peer. * remote peer.
* *
* If both spdylay_session_want_read() and * If both `spdylay_session_want_read()` and
* spdylay_session_want_write() return 0, the application should drop * `spdylay_session_want_write()` return 0, the application should
* the connection. * drop the connection.
*/ */
int spdylay_session_want_read(spdylay_session *session); int spdylay_session_want_read(spdylay_session *session);
/* /**
* Returns nonzero value if |session| want to send data to the remote * @function
* peer, or 0. *
* Returns nonzero value if |session| wants to send data to the remote
* peer.
* *
* If both spdylay_session_want_read() and * If both `spdylay_session_want_read()` and
* spdylay_session_want_write() return 0, the application should drop * `spdylay_session_want_write()` return 0, the application should
* the connection. * drop the connection.
*/ */
int spdylay_session_want_write(spdylay_session *session); int spdylay_session_want_write(spdylay_session *session);
/* /**
* @function
*
* Returns stream_user_data for the stream |stream_id|. The * Returns stream_user_data for the stream |stream_id|. The
* stream_user_data is provided by spdylay_submit_request(). If the * stream_user_data is provided by `spdylay_submit_request()` or
* stream is initiated by the remote endpoint, stream_user_data is * `spdylay_submit_syn_stream()`. If the stream is initiated by the
* always NULL. If the stream is initiated by the local endpoint and * remote endpoint, stream_user_data is always ``NULL``. If the stream
* NULL is given in spdylay_submit_request(), then this function * is initiated by the local endpoint and ``NULL`` is given in
* returns NULL. If the stream does not exist, this function returns * `spdylay_submit_request()` or `spdylay_submit_syn_stream()`, then
* NULL. * this function returns ``NULL``. If the stream does not exist, this
* function returns ``NULL``.
*/ */
void* spdylay_session_get_stream_user_data(spdylay_session *session, void* spdylay_session_get_stream_user_data(spdylay_session *session,
int32_t stream_id); int32_t stream_id);
/* /**
* @function
*
* Submits SYN_STREAM frame and optionally one or more DATA * Submits SYN_STREAM frame and optionally one or more DATA
* frames. * frames.
* *
* |pri| is priority of this request. 0 is the highest priority. If * The |pri| is priority of this request. 0 is the highest priority.
* the |session| is initialized with the version SPDYLAY_PROTO_SPDY2, * If the |session| is initialized with the version
* the lowest priority is 3. If the |session| is initialized with the * :macro:`SPDYLAY_PROTO_SPDY2`, the lowest priority is 3. If the
* version SPDYLAY_PROTO_SPDY3, the lowest priority is 7. * |session| is initialized with the version
* :macro:`SPDYLAY_PROTO_SPDY3`, the lowest priority is 7.
*
* The |nv| contains the name/value pairs. For i > 0, ``nv[2*i]``
* contains a pointer to the name string and ``nv[2*i+1]`` contains a
* pointer to the value string. The one beyond last value must be
* ``NULL``. That is, if the |nv| contains N name/value pairs,
* ``nv[2*N]`` must be ``NULL``.
* *
* The |nv| must include following name/value pairs: * The |nv| must include following name/value pairs:
* *
...@@ -632,40 +1225,41 @@ void* spdylay_session_get_stream_user_data(spdylay_session *session, ...@@ -632,40 +1225,41 @@ void* spdylay_session_get_stream_user_data(spdylay_session *session,
* field. * field.
* *
* If the |session| is initialized with the version * If the |session| is initialized with the version
* SPDYLAY_PROTO_SPDY2, the above names are translated to "method", * :macro:`SPDYLAY_PROTO_SPDY2`, the above names are translated to
* "scheme", "url", "version" and "host" respectively. * "method", "scheme", "url", "version" and "host" respectively.
* *
* This function creates copies of all name/value pairs in |nv|. It * This function creates copies of all name/value pairs in |nv|. It
* also lower-cases all names in |nv|. * also lower-cases all names in |nv|.
* *
* If |data_prd| is not NULL, it provides data which will be sent in * If |data_prd| is not ``NULL``, it provides data which will be sent
* subsequent DATA frames. In this case, a method that allows request * in subsequent DATA frames. In this case, a method that allows
* message bodies * request message bodies
* (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9) must * (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9) must
* be specified with "method" key in |nv| (e.g. POST). If |data_prd| * be specified with "method" key in |nv| (e.g. POST). If |data_prd|
* is NULL, SYN_STREAM have FLAG_FIN. The |stream_user_data| is data * is ``NULL``, SYN_STREAM have FLAG_FIN. The |stream_user_data| is
* associated to the stream opened by this request and can be an * data associated to the stream opened by this request and can be an
* arbitrary pointer, which can be retrieved by * arbitrary pointer, which can be retrieved later by
* spdylay_session_get_stream_user_data(). * `spdylay_session_get_stream_user_data()`.
* *
* Since the library reorders the frames and tries to send the highest * Since the library reorders the frames and tries to send the highest
* prioritized one first and the SPDY specification requires the * prioritized one first and the SPDY specification requires the
* stream ID must be strictly increasing, the stream ID of this * stream ID must be strictly increasing, the stream ID of this
* request cannot be known until it is about to sent. To know the * request cannot be known until it is about to sent. To know the
* stream ID of the request, the application can use * stream ID of the request, the application can use
* before_ctrl_send_callback. This callback is called just before the * :member:`spdylay_session_callbacks.before_ctrl_send_callback`. This
* frame is sent. For SYN_STREAM frame, the argument frame has stream * callback is called just before the frame is sent. For SYN_STREAM
* ID assigned. Also since the stream is already opened, * frame, the argument frame has the stream ID assigned. Also since
* spdylay_session_get_stream_user_data() can be used to get * the stream is already opened,
* `spdylay_session_get_stream_user_data()` can be used to get
* |stream_user_data| to identify which SYN_STREAM we are processing. * |stream_user_data| to identify which SYN_STREAM we are processing.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_INVALID_ARGUMENT * :enum:`SPDYLAY_ERR_INVALID_ARGUMENT`
* The |pri| is invalid; or the Associated-To-Stream-ID is * The |pri| is invalid; or the Associated-To-Stream-ID is
* invalid. * invalid.
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
int spdylay_submit_request(spdylay_session *session, uint8_t pri, int spdylay_submit_request(spdylay_session *session, uint8_t pri,
...@@ -673,9 +1267,17 @@ int spdylay_submit_request(spdylay_session *session, uint8_t pri, ...@@ -673,9 +1267,17 @@ int spdylay_submit_request(spdylay_session *session, uint8_t pri,
const spdylay_data_provider *data_prd, const spdylay_data_provider *data_prd,
void *stream_user_data); void *stream_user_data);
/* /**
* @function
*
* Submits SYN_REPLY frame and optionally one or more DATA frames * Submits SYN_REPLY frame and optionally one or more DATA frames
* against stream |stream_id|. * against the stream |stream_id|.
*
* The |nv| contains the name/value pairs. For i > 0, ``nv[2*i]``
* contains a pointer to the name string and ``nv[2*i+1]`` contains a
* pointer to the value string. The one beyond last value must be
* ``NULL``. That is, if the |nv| contains N name/value pairs,
* ``nv[2*N]`` must be ``NULL``.
* *
* The |nv| must include following name/value pairs: * The |nv| must include following name/value pairs:
* *
...@@ -685,35 +1287,37 @@ int spdylay_submit_request(spdylay_session *session, uint8_t pri, ...@@ -685,35 +1287,37 @@ int spdylay_submit_request(spdylay_session *session, uint8_t pri,
* HTTP response version (e.g., "HTTP/1.1") * HTTP response version (e.g., "HTTP/1.1")
* *
* If the |session| is initialized with the version * If the |session| is initialized with the version
* SPDYLAY_PROTO_SPDY2, the above names are translated to "status" and * :macro:`SPDYLAY_PROTO_SPDY2`, the above names are translated to
* "version" respectively. * "status" and "version" respectively.
* *
* This function creates copies of all name/value pairs in |nv|. It * This function creates copies of all name/value pairs in |nv|. It
* also lower-cases all names in |nv|. * also lower-cases all names in |nv|.
* *
* If |data_prd| is not NULL, it provides data which will be sent in * If |data_prd| is not ``NULL``, it provides data which will be sent
* subsequent DATA frames. If |data_prd| is NULL, SYN_REPLY will have * in subsequent DATA frames. If |data_prd| is ``NULL``, SYN_REPLY
* FLAG_FIN. * will have FLAG_FIN.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
int spdylay_submit_response(spdylay_session *session, int spdylay_submit_response(spdylay_session *session,
int32_t stream_id, const char **nv, int32_t stream_id, const char **nv,
const spdylay_data_provider *data_prd); const spdylay_data_provider *data_prd);
/* /**
* @function
*
* Submits SYN_STREAM frame. The |flags| is bitwise OR of the * Submits SYN_STREAM frame. The |flags| is bitwise OR of the
* following values: * following values:
* *
* SPDYLAY_CTRL_FLAG_FIN * * :enum:`SPDYLAY_CTRL_FLAG_FIN`
* SPDYLAY_CTRL_FLAG_UNIDIRECTIONAL * * :enum:`SPDYLAY_CTRL_FLAG_UNIDIRECTIONAL`
* *
* If |flags| includes SPDYLAY_CTRL_FLAG_FIN, this frame has FIN flag * If |flags| includes :enum:`SPDYLAY_CTRL_FLAG_FIN`, this frame has
* set. * FIN flag set.
* *
* The |assoc_stream_id| is used for server-push. If |session| is * The |assoc_stream_id| is used for server-push. If |session| is
* initialized for client use, |assoc_stream_id| is ignored. The |pri| * initialized for client use, |assoc_stream_id| is ignored. The |pri|
...@@ -722,152 +1326,182 @@ int spdylay_submit_response(spdylay_session *session, ...@@ -722,152 +1326,182 @@ int spdylay_submit_response(spdylay_session *session,
* this frame. The |stream_user_data| is a pointer to an arbitrary * this frame. The |stream_user_data| is a pointer to an arbitrary
* data which is associated to the stream this frame will open. * data which is associated to the stream this frame will open.
* *
* The |nv| contains the name/value pairs. For i > 0, ``nv[2*i]``
* contains a pointer to the name string and ``nv[2*i+1]`` contains a
* pointer to the value string. The one beyond last value must be
* ``NULL``. That is, if the |nv| contains N name/value pairs,
* ``nv[2*N]`` must be ``NULL``.
*
* This function is low-level in a sense that the application code can * This function is low-level in a sense that the application code can
* specify flags and the Associated-To-Stream-ID directly. For usual * specify flags and the Associated-To-Stream-ID directly. For usual
* HTTP request, spdylay_submit_request() is useful. * HTTP request, `spdylay_submit_request()` is useful.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_INVALID_ARGUMENT * :enum:`SPDYLAY_ERR_INVALID_ARGUMENT`
* The |pri| is invalid; or the Associated-To-Stream-ID is * The |pri| is invalid; or the Associated-To-Stream-ID is
* invalid. * invalid.
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
int spdylay_submit_syn_stream(spdylay_session *session, uint8_t flags, int spdylay_submit_syn_stream(spdylay_session *session, uint8_t flags,
int32_t assoc_stream_id, uint8_t pri, int32_t assoc_stream_id, uint8_t pri,
const char **nv, void *stream_user_data); const char **nv, void *stream_user_data);
/* /**
* @function
*
* Submits SYN_REPLY frame. The |flags| is bitwise OR of the following * Submits SYN_REPLY frame. The |flags| is bitwise OR of the following
* values: * values:
* *
* SPDYLAY_CTRL_FLAG_FIN * * :enum:`SPDYLAY_CTRL_FLAG_FIN`
* *
* If |flags| includes SPDYLAY_CTRL_FLAG_FIN, this frame has FIN flag * If |flags| includes :enum:`SPDYLAY_CTRL_FLAG_FIN`, this frame has
* set. * FIN flag set.
*
* The stream which this frame belongs to is given in the
* |stream_id|. The |nv| is the name/value pairs in this frame.
* *
* The stream this frame belongs to is given in |stream_id|. The |nv| * The |nv| contains the name/value pairs. For i > 0, ``nv[2*i]``
* is the name/value pairs in this frame. * contains a pointer to the name string and ``nv[2*i+1]`` contains a
* pointer to the value string. The one beyond last value must be
* ``NULL``. That is, if the |nv| contains N name/value pairs,
* ``nv[2*N]`` must be ``NULL``.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
int spdylay_submit_syn_reply(spdylay_session *session, uint8_t flags, int spdylay_submit_syn_reply(spdylay_session *session, uint8_t flags,
int32_t stream_id, const char **nv); int32_t stream_id, const char **nv);
/* /**
* @function
*
* Submits HEADERS frame. The |flags| is bitwise OR of the following * Submits HEADERS frame. The |flags| is bitwise OR of the following
* values: * values:
* *
* SPDYLAY_CTRL_FLAG_FIN * * :enum:`SPDYLAY_CTRL_FLAG_FIN`
* *
* If |flags| includes SPDYLAY_CTRL_FLAG_FIN, this frame has FIN flag * If |flags| includes :enum:`SPDYLAY_CTRL_FLAG_FIN`, this frame has
* set. * FIN flag set.
* *
* The stream this frame belongs to is given in |stream_id|. The |nv| * The stream which this frame belongs to is given in the
* is the name/value pairs in this frame. * |stream_id|. The |nv| is the name/value pairs in this frame.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
int spdylay_submit_headers(spdylay_session *session, uint8_t flags, int spdylay_submit_headers(spdylay_session *session, uint8_t flags,
int32_t stream_id, const char **nv); int32_t stream_id, const char **nv);
/* /**
* Submits 1 or more DATA frames to the stream |stream_id|. The data * @function
* to be sent are provided by |data_prd|. Depending on the length of *
* data, 1 or more DATA frames will be sent. If |flags| contains * Submits one or more DATA frames to the stream |stream_id|. The
* SPDYLAY_DATA_FLAG_FIN, the last DATA frame has FLAG_FIN set. * data to be sent are provided by |data_prd|. If |flags| contains
* :enum:`SPDYLAY_DATA_FLAG_FIN`, the last DATA frame has FLAG_FIN
* set.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
int spdylay_submit_data(spdylay_session *session, int32_t stream_id, int spdylay_submit_data(spdylay_session *session, int32_t stream_id,
uint8_t flags, const spdylay_data_provider *data_prd); uint8_t flags, const spdylay_data_provider *data_prd);
/* /**
* Submits RST_STREAM frame to cancel/reject stream |stream_id| with * @function
* status code |status_code|. *
* Submits RST_STREAM frame to cancel/reject the stream |stream_id|
* with the status code |status_code|.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
int spdylay_submit_rst_stream(spdylay_session *session, int32_t stream_id, int spdylay_submit_rst_stream(spdylay_session *session, int32_t stream_id,
uint32_t status_code); uint32_t status_code);
/* /**
* @function
*
* Submits PING frame. * Submits PING frame.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
int spdylay_submit_ping(spdylay_session *session); int spdylay_submit_ping(spdylay_session *session);
/* /**
* @function
*
* Submits GOAWAY frame. The status code |status_code| is ignored if * Submits GOAWAY frame. The status code |status_code| is ignored if
* the protocol version is SPDYLAY_PROTO_SPDY2. * the protocol version is :macro:`SPDYLAY_PROTO_SPDY2`.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
int spdylay_submit_goaway(spdylay_session *session, uint32_t status_code); int spdylay_submit_goaway(spdylay_session *session, uint32_t status_code);
/* /**
* @function
*
* Stores local settings and submits SETTINGS frame. The |iv| is the * Stores local settings and submits SETTINGS frame. The |iv| is the
* pointer to the array of spdylay_settings_entry. The |niv| indicates * pointer to the array of :type:`spdylay_settings_entry`. The |niv|
* the number of spdylay_settings_entry. The |flags| is bitwise-OR of * indicates the number of :type:`spdylay_settings_entry`. The |flags|
* one or more values from spdylay_settings_flag. * is bitwise-OR of one or more values from
* :type:`spdylay_settings_flag`.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_INVALID_ARGUMENT * :enum:`SPDYLAY_ERR_INVALID_ARGUMENT`
* The |iv| contains duplicate settings ID or invalid value. * The |iv| contains duplicate settings ID or invalid value.
* SPDYLAY_ERR_NOMEM * :enum:`SPDYLAY_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
int spdylay_submit_settings(spdylay_session *session, uint8_t flags, int spdylay_submit_settings(spdylay_session *session, uint8_t flags,
const spdylay_settings_entry *iv, size_t niv); const spdylay_settings_entry *iv, size_t niv);
/* /**
* A helper function for dealing with NPN in client side. * @function
* |in| contains server's protocol in preferable order. *
* The format of |in| is length-prefixed and not null-terminated. * A helper function for dealing with NPN in client side. The |in|
* For example, "spdy/2" are "http/1.1" stored in |in| like this: * contains server's protocol in preferable order. The format of |in|
* is length-prefixed and not null-terminated. For example, "spdy/2"
* are "http/1.1" stored in |in| like this::
* *
* in[0] = 6 * in[0] = 6
* in[1..6] = "spdy/2" * in[1..6] = "spdy/2"
* in[7] = 8 * in[7] = 8
* in[8..15] = "http/1.1" * in[8..15] = "http/1.1"
* inlen = 16 * inlen = 16
* *
* The selection algorithm is as follows: * The selection algorithm is as follows:
* *
* 1. If server's list contains SPDY versions the spdylay library * 1. If server's list contains SPDY versions the spdylay library
* supports, this function selects one of them and returns its SPDY * supports, this function selects one of them and returns its SPDY
* protocol version which can be used directly with * protocol version which can be used directly with
* spdylay_session_client_new() and spdylay_session_server_new() * `spdylay_session_client_new()` and
* . The following steps are not taken. * `spdylay_session_server_new()` . The following steps are not
* taken.
* *
* 2. If server's list contains "http/1.1", this function selects * 2. If server's list contains "http/1.1", this function selects
* "http/1.1" and returns 0. The following step is not taken. * "http/1.1" and returns 0. The following step is not taken.
...@@ -886,27 +1520,31 @@ int spdylay_submit_settings(spdylay_session *session, uint8_t flags, ...@@ -886,27 +1520,31 @@ int spdylay_submit_settings(spdylay_session *session, uint8_t flags,
* See http://technotes.googlecode.com/git/nextprotoneg.html for more * See http://technotes.googlecode.com/git/nextprotoneg.html for more
* details about NPN. * details about NPN.
* *
* To use this method you should do something like: * To use this method you should do something like::
* *
* static int select_next_proto_cb(SSL* ssl, * static int select_next_proto_cb(SSL* ssl,
* unsigned char **out, unsigned char *outlen, * unsigned char **out,
* const unsigned char *in, unsigned int inlen, * unsigned char *outlen,
* void *arg) * const unsigned char *in,
* { * unsigned int inlen,
* int version; * void *arg)
* version = spdylay_select_next_protocol(out, outlen, in, inlen); * {
* if(version > 0) { * int version;
* ((MyType*)arg)->spdy_version = version; * version = spdylay_select_next_protocol(out, outlen, in, inlen);
* } * if(version > 0) {
* return SSL_TLSEXT_ERR_OK; * ((MyType*)arg)->spdy_version = version;
* } * }
* ... * return SSL_TLSEXT_ERR_OK;
* SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, my_obj); * }
* ...
* SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, my_obj);
*/ */
int spdylay_select_next_protocol(unsigned char **out, unsigned char *outlen, int spdylay_select_next_protocol(unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen); const unsigned char *in, unsigned int inlen);
/* /**
* @function
*
* Returns spdy version which spdylay library supports from given * Returns spdy version which spdylay library supports from given
* protocol name. The |proto| is the pointer to the protocol name and * protocol name. The |proto| is the pointer to the protocol name and
* |protolen| is its length. Currently, "spdy/2" and "spdy/3" are * |protolen| is its length. Currently, "spdy/2" and "spdy/3" are
......
...@@ -25,7 +25,10 @@ ...@@ -25,7 +25,10 @@
#ifndef SPDYLAYVER_H #ifndef SPDYLAYVER_H
#define SPDYLAYVER_H #define SPDYLAYVER_H
/* Version number of spdylay release */ /**
* @macro
* Version number of spdylay release
*/
#define SPDYLAY_VERSION "@PACKAGE_VERSION@" #define SPDYLAY_VERSION "@PACKAGE_VERSION@"
#endif /* SPDYLAYVER_H */ #endif /* SPDYLAYVER_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment