[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r36708 - in libmicrohttpd: . m4 src src/datadir src/example
From: |
gnunet |
Subject: |
[GNUnet-SVN] r36708 - in libmicrohttpd: . m4 src src/datadir src/examples src/include |
Date: |
Tue, 1 Dec 2015 14:06:38 +0100 |
Author: grothoff
Date: 2015-12-01 14:06:38 +0100 (Tue, 01 Dec 2015)
New Revision: 36708
Removed:
libmicrohttpd/libmicrospdy.pc.in
libmicrohttpd/m4/ax_check_openssl.m4
libmicrohttpd/src/datadir/spdy-draft.txt
libmicrohttpd/src/examples/mhd2spdy.c
libmicrohttpd/src/examples/mhd2spdy_http.c
libmicrohttpd/src/examples/mhd2spdy_http.h
libmicrohttpd/src/examples/mhd2spdy_spdy.c
libmicrohttpd/src/examples/mhd2spdy_spdy.h
libmicrohttpd/src/examples/mhd2spdy_structures.c
libmicrohttpd/src/examples/mhd2spdy_structures.h
libmicrohttpd/src/examples/spdy_event_loop.c
libmicrohttpd/src/examples/spdy_fileserver.c
libmicrohttpd/src/examples/spdy_response_with_callback.c
libmicrohttpd/src/include/microspdy.h
libmicrohttpd/src/microspdy/
libmicrohttpd/src/spdy2http/
libmicrohttpd/src/testspdy/
Modified:
libmicrohttpd/ChangeLog
libmicrohttpd/Makefile.am
libmicrohttpd/configure.ac
libmicrohttpd/src/Makefile.am
libmicrohttpd/src/examples/Makefile.am
libmicrohttpd/src/include/Makefile.am
Log:
killing libmicrospdy
Modified: libmicrohttpd/ChangeLog
===================================================================
--- libmicrohttpd/ChangeLog 2015-12-01 10:19:37 UTC (rev 36707)
+++ libmicrohttpd/ChangeLog 2015-12-01 13:06:38 UTC (rev 36708)
@@ -1,3 +1,6 @@
+Tue Dec 1 14:05:13 CET 2015
+ SPDY is dead, killing experimental libmicrospdy. -CG
+
Tue Dec 1 10:01:12 CET 2015
New logic for controlling socket buffer modes.
Eliminated delay before last packet in response and before
Modified: libmicrohttpd/Makefile.am
===================================================================
--- libmicrohttpd/Makefile.am 2015-12-01 10:19:37 UTC (rev 36707)
+++ libmicrohttpd/Makefile.am 2015-12-01 13:06:38 UTC (rev 36708)
@@ -8,9 +8,6 @@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmicrohttpd.pc
-if ENABLE_SPDY
-pkgconfig_DATA += libmicrospdy.pc
-endif
if BUILD_DOC
SUBDIRS += doc
Modified: libmicrohttpd/configure.ac
===================================================================
--- libmicrohttpd/configure.ac 2015-12-01 10:19:37 UTC (rev 36707)
+++ libmicrohttpd/configure.ac 2015-12-01 13:06:38 UTC (rev 36708)
@@ -595,77 +595,6 @@
AM_CONDITIONAL(HAVE_MAGIC, false))
-# optional: libmicrospdy support. Enabled by default if not on W32
-AC_ARG_ENABLE([spdy],
- AS_HELP_STRING([--enable-spdy],
- [enable build libmicrospdy (yes, no, auto) [auto]]),
- [enable_spdy=${enableval}],
- [ AS_IF([[test "x$os_is_windows" = "xyes"]], [enable_spdy=no])
])
-
-if test "$enable_spdy" != "no"
-then
- AX_CHECK_OPENSSL([ have_openssl=yes ],[ have_openssl=no ])
- if test "x$have_openssl" = "xyes"
- then
- # check OpenSSL headers
- SAVE_CPP_FLAGS="$CPPFLAGS"
- CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
- AC_CHECK_HEADERS([openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h
openssl/sha.h openssl/pem.h openssl/engine.h], [ have_openssl=yes ],[
have_openssl=no ])
- if test "x$have_openssl" = "xyes"
- then
- # check OpenSSL libs
- SAVE_LIBS="$LIBS"
- SAVE_LD_FLAGS="$LDFLAGS"
- LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
- LIBS="$OPENSSL_LIBS $LIBS"
- AC_CHECK_FUNC([SSL_CTX_set_next_protos_advertised_cb],
- [
- AC_CHECK_FUNC([SSL_library_init], [ have_openssl=yes ],[
have_openssl=no ])
- ],[ have_openssl=no ])
- LIBS="$SAVE_LIBS"
- LDFLAGS="$SAVE_LD_FLAGS"
- fi
- CPPFLAGS="$SAVE_CPP_FLAGS"
- fi
- if test "x$have_openssl" = "xyes"
- then
- enable_spdy=yes
- else
- AS_IF([[test "x$enable_spdy" = "xyes" ]], [AC_MSG_ERROR([[libmicrospdy
cannot be enabled without OpenSSL.]])])
- have_openssl=no
- enable_spdy=no
- fi
-else
- # OpenSSL is used only for libmicrospdy
- have_openssl=no
-fi
-AM_CONDITIONAL([HAVE_OPENSSL], [test "x$have_openssl" = "xyes"])
-
-if test "$enable_spdy" = "yes"
-then
- AC_DEFINE([SPDY_SUPPORT],[1],[include libmicrospdy support])
-else
- AC_DEFINE([SPDY_SUPPORT],[0],[disable libmicrospdy support])
-fi
-AM_CONDITIONAL(ENABLE_SPDY, [test "x$enable_spdy" != "xno"])
-AC_MSG_CHECKING(whether we have OpenSSL and thus can support libmicrospdy)
-AC_MSG_RESULT($enable_spdy)
-
-# for pkg-config
-SPDY_LIBDEPS="$OPENSSL_LIBS"
-
-SPDY_LIB_LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
-SPDY_LIB_CFLAGS="$CFLAGS"
-SPDY_LIB_CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
-AC_SUBST(SPDY_LIB_LDFLAGS)
-AC_SUBST(SPDY_LIB_CFLAGS)
-AC_SUBST(SPDY_LIB_CPPFLAGS)
-# for pkg-config
-AC_SUBST(SPDY_LIBDEPS)
-
-AC_CHECK_HEADERS([spdylay/spdylay.h], [ have_spdylay="yes" ],
[have_spdylay="no"])
-AM_CONDITIONAL(HAVE_SPDYLAY, [test "x$have_spdylay" = "xyes"])
-
# large file support (> 4 GB)
AC_SYS_LARGEFILE
AC_FUNC_FSEEKO
@@ -946,7 +875,6 @@
AC_CONFIG_FILES([
libmicrohttpd.pc
-libmicrospdy.pc
w32/VS2013/microhttpd_dll_res_vc.rc
Makefile
contrib/Makefile
@@ -958,12 +886,9 @@
src/include/Makefile
src/platform/Makefile
src/microhttpd/Makefile
-src/microspdy/Makefile
-src/spdy2http/Makefile
src/examples/Makefile
src/testcurl/Makefile
src/testcurl/https/Makefile
-src/testspdy/Makefile
src/testzzuf/Makefile])
AC_OUTPUT
@@ -989,8 +914,6 @@
epoll support: ${enable_epoll=no}
build docs: ${enable_doc}
build examples: ${enable_examples}
- libmicrospdy: ${enable_spdy}
- spdylay (testing): ${have_spdylay}
])
if test "x$enable_https" = "xyes"
Deleted: libmicrohttpd/libmicrospdy.pc.in
===================================================================
--- libmicrohttpd/libmicrospdy.pc.in 2015-12-01 10:19:37 UTC (rev 36707)
+++ libmicrohttpd/libmicrospdy.pc.in 2015-12-01 13:06:38 UTC (rev 36708)
@@ -1,13 +0,0 @@
address@hidden@
address@hidden@
address@hidden@
address@hidden@
-
-Name: libmicrospdy
-Description: A library for creating an embedded SPDY server
-Version: @VERSION@
-Requires:
-Conflicts:
-Libs: -L${libdir} -lmicrospdy
-Libs.private: @SPDY_LIBDEPS@
-Cflags: -I${includedir}
Deleted: libmicrohttpd/m4/ax_check_openssl.m4
===================================================================
--- libmicrohttpd/m4/ax_check_openssl.m4 2015-12-01 10:19:37 UTC (rev
36707)
+++ libmicrohttpd/m4/ax_check_openssl.m4 2015-12-01 13:06:38 UTC (rev
36708)
@@ -1,124 +0,0 @@
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]])
-#
-# DESCRIPTION
-#
-# Look for OpenSSL in a number of default spots, or in a user-selected
-# spot (via --with-openssl). Sets
-#
-# OPENSSL_INCLUDES to the include directives required
-# OPENSSL_LIBS to the -l directives required
-# OPENSSL_LDFLAGS to the -L or -R flags required
-#
-# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately
-#
-# This macro sets OPENSSL_INCLUDES such that source files should use the
-# openssl/ directory in include directives:
-#
-# #include <openssl/hmac.h>
-#
-# LICENSE
-#
-# Copyright (c) 2009,2010 Zmanda Inc. <http://www.zmanda.com/>
-# Copyright (c) 2009,2010 Dustin J. Mitchell <address@hidden>
-#
-# Copying and distribution of this file, with or without modification, are
-# permitted in any medium without royalty provided the copyright notice
-# and this notice are preserved. This file is offered as-is, without any
-# warranty.
-
-#serial 8
-
-AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL])
-AC_DEFUN([AX_CHECK_OPENSSL], [
- found=false
- AC_ARG_WITH([openssl],
- [AS_HELP_STRING([--with-openssl=DIR],
- [root of the OpenSSL directory])],
- [
- case "$withval" in
- "" | y | ye | yes | n | no)
- AC_MSG_ERROR([Invalid --with-openssl value])
- ;;
- *) ssldirs="$withval"
- ;;
- esac
- ], [
- # if pkg-config is installed and openssl has installed a .pc file,
- # then use that information and don't search ssldirs
- AC_PATH_PROG([PKG_CONFIG], [pkg-config])
- if test x"$PKG_CONFIG" != x""; then
- OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null`
- if test $? = 0; then
- OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l
2>/dev/null`
- OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I
2>/dev/null`
- found=true
- fi
- fi
-
- # no such luck; use some default ssldirs
- if ! $found; then
- ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg
/usr/local /usr"
- fi
- ]
- )
-
-
- # note that we #include <openssl/foo.h>, so the OpenSSL headers have to be
in
- # an 'openssl' subdirectory
-
- if ! $found; then
- OPENSSL_INCLUDES=
- for ssldir in $ssldirs; do
- AC_MSG_CHECKING([for openssl/ssl.h in $ssldir])
- if test -f "$ssldir/include/openssl/ssl.h"; then
- OPENSSL_INCLUDES="-I$ssldir/include"
- OPENSSL_LDFLAGS="-L$ssldir/lib"
- OPENSSL_LIBS="-lssl -lcrypto"
- found=true
- AC_MSG_RESULT([yes])
- break
- else
- AC_MSG_RESULT([no])
- fi
- done
-
- # if the file wasn't found, well, go ahead and try the link anyway --
maybe
- # it will just work!
- fi
-
- # try the preprocessor and linker with our new flags,
- # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS
-
- AC_MSG_CHECKING([whether compiling and linking against OpenSSL works])
- echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \
- "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES"
>&AS_MESSAGE_LOG_FD
-
- save_LIBS="$LIBS"
- save_LDFLAGS="$LDFLAGS"
- save_CPPFLAGS="$CPPFLAGS"
- LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
- LIBS="$OPENSSL_LIBS $LIBS"
- CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
- AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([#include <openssl/ssl.h>], [SSL_new(NULL)])],
- [
- AC_MSG_RESULT([yes])
- $1
- ], [
- AC_MSG_RESULT([no])
- $2
- ])
- CPPFLAGS="$save_CPPFLAGS"
- LDFLAGS="$save_LDFLAGS"
- LIBS="$save_LIBS"
-
- AC_SUBST([OPENSSL_INCLUDES])
- AC_SUBST([OPENSSL_LIBS])
- AC_SUBST([OPENSSL_LDFLAGS])
-])
Modified: libmicrohttpd/src/Makefile.am
===================================================================
--- libmicrohttpd/src/Makefile.am 2015-12-01 10:19:37 UTC (rev 36707)
+++ libmicrohttpd/src/Makefile.am 2015-12-01 13:06:38 UTC (rev 36708)
@@ -7,19 +7,8 @@
endif
endif
endif
-if ENABLE_SPDY
-if HAVE_OPENSSL
-microspdy = microspdy
-if HAVE_CURL
-microspdy += spdy2http
-endif
-#if HAVE_SPDYLAY
-microspdy += testspdy
-#endif
-endif
-endif
-SUBDIRS = include platform microhttpd $(microspdy) $(curltests) $(zzuftests) .
+SUBDIRS = include platform microhttpd $(curltests) $(zzuftests) .
if BUILD_EXAMPLES
SUBDIRS += examples
@@ -27,5 +16,4 @@
EXTRA_DIST = \
datadir/cert-and-key.pem \
- datadir/cert-and-key-for-wireshark.pem \
- datadir/spdy-draft.txt
+ datadir/cert-and-key-for-wireshark.pem
Deleted: libmicrohttpd/src/datadir/spdy-draft.txt
===================================================================
--- libmicrohttpd/src/datadir/spdy-draft.txt 2015-12-01 10:19:37 UTC (rev
36707)
+++ libmicrohttpd/src/datadir/spdy-draft.txt 2015-12-01 13:06:38 UTC (rev
36708)
@@ -1,2856 +0,0 @@
-
-
-
-Network Working Group M. Belshe
-Internet-Draft Twist
-Expires: August 4, 2012 R. Peon
- Google, Inc
- Feb 2012
-
-
- SPDY Protocol
- draft-mbelshe-httpbis-spdy-00
-
-Abstract
-
- This document describes SPDY, a protocol designed for low-latency
- transport of content over the World Wide Web. SPDY introduces two
- layers of protocol. The lower layer is a general purpose framing
- layer which can be used atop a reliable transport (likely TCP) for
- multiplexed, prioritized, and compressed data communication of many
- concurrent streams. The upper layer of the protocol provides HTTP-
- like RFC2616 [RFC2616] semantics for compatibility with existing HTTP
- application servers.
-
-Status of this Memo
-
- This Internet-Draft is submitted in full conformance with the
- provisions of BCP 78 and BCP 79.
-
- Internet-Drafts are working documents of the Internet Engineering
- Task Force (IETF). Note that other groups may also distribute
- working documents as Internet-Drafts. The list of current Internet-
- Drafts is at http://datatracker.ietf.org/drafts/current/.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference
- material or to cite them other than as "work in progress."
-
- This Internet-Draft will expire on August 4, 2012.
-
-Copyright Notice
-
- Copyright (c) 2012 IETF Trust and the persons identified as the
- document authors. All rights reserved.
-
- This document is subject to BCP 78 and the IETF Trust's Legal
- Provisions Relating to IETF Documents
- (http://trustee.ietf.org/license-info) in effect on the date of
- publication of this document. Please review these documents
- carefully, as they describe your rights and restrictions with respect
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 1]
-
-Internet-Draft SPDY Feb 2012
-
-
- to this document. Code Components extracted from this document must
- include Simplified BSD License text as described in Section 4.e of
- the Trust Legal Provisions and are provided without warranty as
- described in the Simplified BSD License.
-
-
-Table of Contents
-
- 1. Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
- 1.1. Document Organization . . . . . . . . . . . . . . . . . . 4
- 1.2. Definitions . . . . . . . . . . . . . . . . . . . . . . . 5
- 2. SPDY Framing Layer . . . . . . . . . . . . . . . . . . . . . . 6
- 2.1. Session (Connections) . . . . . . . . . . . . . . . . . . 6
- 2.2. Framing . . . . . . . . . . . . . . . . . . . . . . . . . 6
- 2.2.1. Control frames . . . . . . . . . . . . . . . . . . . . 6
- 2.2.2. Data frames . . . . . . . . . . . . . . . . . . . . . 7
- 2.3. Streams . . . . . . . . . . . . . . . . . . . . . . . . . 8
- 2.3.1. Stream frames . . . . . . . . . . . . . . . . . . . . 9
- 2.3.2. Stream creation . . . . . . . . . . . . . . . . . . . 9
- 2.3.3. Stream priority . . . . . . . . . . . . . . . . . . . 10
- 2.3.4. Stream headers . . . . . . . . . . . . . . . . . . . . 10
- 2.3.5. Stream data exchange . . . . . . . . . . . . . . . . . 10
- 2.3.6. Stream half-close . . . . . . . . . . . . . . . . . . 10
- 2.3.7. Stream close . . . . . . . . . . . . . . . . . . . . . 11
- 2.4. Error Handling . . . . . . . . . . . . . . . . . . . . . . 11
- 2.4.1. Session Error Handling . . . . . . . . . . . . . . . . 11
- 2.4.2. Stream Error Handling . . . . . . . . . . . . . . . . 12
- 2.5. Data flow . . . . . . . . . . . . . . . . . . . . . . . . 12
- 2.6. Control frame types . . . . . . . . . . . . . . . . . . . 12
- 2.6.1. SYN_STREAM . . . . . . . . . . . . . . . . . . . . . . 12
- 2.6.2. SYN_REPLY . . . . . . . . . . . . . . . . . . . . . . 14
- 2.6.3. RST_STREAM . . . . . . . . . . . . . . . . . . . . . . 15
- 2.6.4. SETTINGS . . . . . . . . . . . . . . . . . . . . . . . 16
- 2.6.5. PING . . . . . . . . . . . . . . . . . . . . . . . . . 19
- 2.6.6. GOAWAY . . . . . . . . . . . . . . . . . . . . . . . . 20
- 2.6.7. HEADERS . . . . . . . . . . . . . . . . . . . . . . . 21
- 2.6.8. WINDOW_UPDATE . . . . . . . . . . . . . . . . . . . . 22
- 2.6.9. CREDENTIAL . . . . . . . . . . . . . . . . . . . . . . 24
- 2.6.10. Name/Value Header Block . . . . . . . . . . . . . . . 26
- 3. HTTP Layering over SPDY . . . . . . . . . . . . . . . . . . . 33
- 3.1. Connection Management . . . . . . . . . . . . . . . . . . 33
- 3.1.1. Use of GOAWAY . . . . . . . . . . . . . . . . . . . . 33
- 3.2. HTTP Request/Response . . . . . . . . . . . . . . . . . . 34
- 3.2.1. Request . . . . . . . . . . . . . . . . . . . . . . . 34
- 3.2.2. Response . . . . . . . . . . . . . . . . . . . . . . . 35
- 3.2.3. Authentication . . . . . . . . . . . . . . . . . . . . 36
- 3.3. Server Push Transactions . . . . . . . . . . . . . . . . . 37
- 3.3.1. Server implementation . . . . . . . . . . . . . . . . 38
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 2]
-
-Internet-Draft SPDY Feb 2012
-
-
- 3.3.2. Client implementation . . . . . . . . . . . . . . . . 39
- 4. Design Rationale and Notes . . . . . . . . . . . . . . . . . . 40
- 4.1. Separation of Framing Layer and Application Layer . . . . 40
- 4.2. Error handling - Framing Layer . . . . . . . . . . . . . . 40
- 4.3. One Connection Per Domain . . . . . . . . . . . . . . . . 40
- 4.4. Fixed vs Variable Length Fields . . . . . . . . . . . . . 41
- 4.5. Compression Context(s) . . . . . . . . . . . . . . . . . . 41
- 4.6. Unidirectional streams . . . . . . . . . . . . . . . . . . 42
- 4.7. Data Compression . . . . . . . . . . . . . . . . . . . . . 42
- 4.8. Server Push . . . . . . . . . . . . . . . . . . . . . . . 42
- 5. Security Considerations . . . . . . . . . . . . . . . . . . . 43
- 5.1. Use of Same-origin constraints . . . . . . . . . . . . . . 43
- 5.2. HTTP Headers and SPDY Headers . . . . . . . . . . . . . . 43
- 5.3. Cross-Protocol Attacks . . . . . . . . . . . . . . . . . . 43
- 5.4. Server Push Implicit Headers . . . . . . . . . . . . . . . 43
- 6. Privacy Considerations . . . . . . . . . . . . . . . . . . . . 44
- 6.1. Long Lived Connections . . . . . . . . . . . . . . . . . . 44
- 6.2. SETTINGS frame . . . . . . . . . . . . . . . . . . . . . . 44
- 7. Incompatibilities with SPDY draft #2 . . . . . . . . . . . . . 45
- 8. Requirements Notation . . . . . . . . . . . . . . . . . . . . 46
- 9. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 47
- 10. Normative References . . . . . . . . . . . . . . . . . . . . . 48
- Appendix A. Changes . . . . . . . . . . . . . . . . . . . . . . . 50
- Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 51
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 3]
-
-Internet-Draft SPDY Feb 2012
-
-
-1. Overview
-
- One of the bottlenecks of HTTP implementations is that HTTP relies on
- multiple connections for concurrency. This causes several problems,
- including additional round trips for connection setup, slow-start
- delays, and connection rationing by the client, where it tries to
- avoid opening too many connections to any single server. HTTP
- pipelining helps some, but only achieves partial multiplexing. In
- addition, pipelining has proven non-deployable in existing browsers
- due to intermediary interference.
-
- SPDY adds a framing layer for multiplexing multiple, concurrent
- streams across a single TCP connection (or any reliable transport
- stream). The framing layer is optimized for HTTP-like request-
- response streams, such that applications which run over HTTP today
- can work over SPDY with little or no change on behalf of the web
- application writer.
-
- The SPDY session offers four improvements over HTTP:
-
- Multiplexed requests: There is no limit to the number of requests
- that can be issued concurrently over a single SPDY connection.
-
- Prioritized requests: Clients can request certain resources to be
- delivered first. This avoids the problem of congesting the
- network channel with non-critical resources when a high-priority
- request is pending.
-
- Compressed headers: Clients today send a significant amount of
- redundant data in the form of HTTP headers. Because a single web
- page may require 50 or 100 subrequests, this data is significant.
-
- Server pushed streams: Server Push enables content to be pushed
- from servers to clients without a request.
-
- SPDY attempts to preserve the existing semantics of HTTP. All
- features such as cookies, ETags, Vary headers, Content-Encoding
- negotiations, etc work as they do with HTTP; SPDY only replaces the
- way the data is written to the network.
-
-1.1. Document Organization
-
- The SPDY Specification is split into two parts: a framing layer
- (Section 2), which multiplexes a TCP connection into independent,
- length-prefixed frames, and an HTTP layer (Section 3), which
- specifies the mechanism for overlaying HTTP request/response pairs on
- top of the framing layer. While some of the framing layer concepts
- are isolated from the HTTP layer, building a generic framing layer
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 4]
-
-Internet-Draft SPDY Feb 2012
-
-
- has not been a goal. The framing layer is tailored to the needs of
- the HTTP protocol and server push.
-
-1.2. Definitions
-
- client: The endpoint initiating the SPDY session.
-
- connection: A transport-level connection between two endpoints.
-
- endpoint: Either the client or server of a connection.
-
- frame: A header-prefixed sequence of bytes sent over a SPDY
- session.
-
- server: The endpoint which did not initiate the SPDY session.
-
- session: A synonym for a connection.
-
- session error: An error on the SPDY session.
-
- stream: A bi-directional flow of bytes across a virtual channel
- within a SPDY session.
-
- stream error: An error on an individual SPDY stream.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 5]
-
-Internet-Draft SPDY Feb 2012
-
-
-2. SPDY Framing Layer
-
-2.1. Session (Connections)
-
- The SPDY framing layer (or "session") runs atop a reliable transport
- layer such as TCP [RFC0793]. The client is the TCP connection
- initiator. SPDY connections are persistent connections.
-
- For best performance, it is expected that clients will not close open
- connections until the user navigates away from all web pages
- referencing a connection, or until the server closes the connection.
- Servers are encouraged to leave connections open for as long as
- possible, but can terminate idle connections if necessary. When
- either endpoint closes the transport-level connection, it MUST first
- send a GOAWAY (Section 2.6.6) frame so that the endpoints can
- reliably determine if requests finished before the close.
-
-2.2. Framing
-
- Once the connection is established, clients and servers exchange
- framed messages. There are two types of frames: control frames
- (Section 2.2.1) and data frames (Section 2.2.2). Frames always have
- a common header which is 8 bytes in length.
-
- The first bit is a control bit indicating whether a frame is a
- control frame or data frame. Control frames carry a version number,
- a frame type, flags, and a length. Data frames contain the stream
- ID, flags, and the length for the payload carried after the common
- header. The simple header is designed to make reading and writing of
- frames easy.
-
- All integer values, including length, version, and type, are in
- network byte order. SPDY does not enforce alignment of types in
- dynamically sized frames.
-
-2.2.1. Control frames
-
- +----------------------------------+
- |C| Version(15bits) | Type(16bits) |
- +----------------------------------+
- | Flags (8) | Length (24 bits) |
- +----------------------------------+
- | Data |
- +----------------------------------+
-
- Control bit: The 'C' bit is a single bit indicating if this is a
- control message. For control frames this value is always 1.
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 6]
-
-Internet-Draft SPDY Feb 2012
-
-
- Version: The version number of the SPDY protocol. This document
- describes SPDY version 3.
-
- Type: The type of control frame. See Control Frames for the complete
- list of control frames.
-
- Flags: Flags related to this frame. Flags for control frames and
- data frames are different.
-
- Length: An unsigned 24-bit value representing the number of bytes
- after the length field.
-
- Data: data associated with this control frame. The format and length
- of this data is controlled by the control frame type.
-
- Control frame processing requirements:
-
- Note that full length control frames (16MB) can be large for
- implementations running on resource-limited hardware. In such
- cases, implementations MAY limit the maximum length frame
- supported. However, all implementations MUST be able to receive
- control frames of at least 8192 octets in length.
-
-2.2.2. Data frames
-
- +----------------------------------+
- |C| Stream-ID (31bits) |
- +----------------------------------+
- | Flags (8) | Length (24 bits) |
- +----------------------------------+
- | Data |
- +----------------------------------+
-
- Control bit: For data frames this value is always 0.
-
- Stream-ID: A 31-bit value identifying the stream.
-
- Flags: Flags related to this frame. Valid flags are:
-
- 0x01 = FLAG_FIN - signifies that this frame represents the last
- frame to be transmitted on this stream. See Stream Close
- (Section 2.3.7) below.
-
- 0x02 = FLAG_COMPRESS - indicates that the data in this frame has
- been compressed.
-
- Length: An unsigned 24-bit value representing the number of bytes
- after the length field. The total size of a data frame is 8 bytes +
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 7]
-
-Internet-Draft SPDY Feb 2012
-
-
- length. It is valid to have a zero-length data frame.
-
- Data: The variable-length data payload; the length was defined in the
- length field.
-
- Data frame processing requirements:
-
- If an endpoint receives a data frame for a stream-id which is not
- open and the endpoint has not sent a GOAWAY (Section 2.6.6) frame,
- it MUST send issue a stream error (Section 2.4.2) with the error
- code INVALID_STREAM for the stream-id.
-
- If the endpoint which created the stream receives a data frame
- before receiving a SYN_REPLY on that stream, it is a protocol
- error, and the recipient MUST issue a stream error (Section 2.4.2)
- with the status code PROTOCOL_ERROR for the stream-id.
-
- Implementors note: If an endpoint receives multiple data frames
- for invalid stream-ids, it MAY close the session.
-
- All SPDY endpoints MUST accept compressed data frames.
- Compression of data frames is always done using zlib compression.
- Each stream initializes and uses its own compression context
- dedicated to use within that stream. Endpoints are encouraged to
- use application level compression rather than SPDY stream level
- compression.
-
- Each SPDY stream sending compressed frames creates its own zlib
- context for that stream, and these compression contexts MUST be
- distinct from the compression contexts used with SYN_STREAM/
- SYN_REPLY/HEADER compression. (Thus, if both endpoints of a
- stream are compressing data on the stream, there will be two zlib
- contexts, one for sending and one for receiving).
-
-2.3. Streams
-
- Streams are independent sequences of bi-directional data divided into
- frames with several properties:
-
- Streams may be created by either the client or server.
-
- Streams optionally carry a set of name/value header pairs.
-
- Streams can concurrently send data interleaved with other streams.
-
- Streams may be cancelled.
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 8]
-
-Internet-Draft SPDY Feb 2012
-
-
-2.3.1. Stream frames
-
- SPDY defines 3 control frames to manage the lifecycle of a stream:
-
- SYN_STREAM - Open a new stream
-
- SYN_REPLY - Remote acknowledgement of a new, open stream
-
- RST_STREAM - Close a stream
-
-2.3.2. Stream creation
-
- A stream is created by sending a control frame with the type set to
- SYN_STREAM (Section 2.6.1). If the server is initiating the stream,
- the Stream-ID must be even. If the client is initiating the stream,
- the Stream-ID must be odd. 0 is not a valid Stream-ID. Stream-IDs
- from each side of the connection must increase monotonically as new
- streams are created. E.g. Stream 2 may be created after stream 3,
- but stream 7 must not be created after stream 9. Stream IDs do not
- wrap: when a client or server cannot create a new stream id without
- exceeding a 31 bit value, it MUST NOT create a new stream.
-
- The stream-id MUST increase with each new stream. If an endpoint
- receives a SYN_STREAM with a stream id which is less than any
- previously received SYN_STREAM, it MUST issue a session error
- (Section 2.4.1) with the status PROTOCOL_ERROR.
-
- It is a protocol error to send two SYN_STREAMs with the same
- stream-id. If a recipient receives a second SYN_STREAM for the same
- stream, it MUST issue a stream error (Section 2.4.2) with the status
- code PROTOCOL_ERROR.
-
- Upon receipt of a SYN_STREAM, the recipient can reject the stream by
- sending a stream error (Section 2.4.2) with the error code
- REFUSED_STREAM. Note, however, that the creating endpoint may have
- already sent additional frames for that stream which cannot be
- immediately stopped.
-
- Once the stream is created, the creator may immediately send HEADERS
- or DATA frames for that stream, without needing to wait for the
- recipient to acknowledge.
-
-2.3.2.1. Unidirectional streams
-
- When an endpoint creates a stream with the FLAG_UNIDIRECTIONAL flag
- set, it creates a unidirectional stream which the creating endpoint
- can use to send frames, but the receiving endpoint cannot. The
- receiving endpoint is implicitly already in the half-closed
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 9]
-
-Internet-Draft SPDY Feb 2012
-
-
- (Section 2.3.6) state.
-
-2.3.2.2. Bidirectional streams
-
- SYN_STREAM frames which do not use the FLAG_UNIDIRECTIONAL flag are
- bidirectional streams. Both endpoints can send data on a bi-
- directional stream.
-
-2.3.3. Stream priority
-
- The creator of a stream assigns a priority for that stream. Priority
- is represented as an integer from 0 to 7. 0 represents the highest
- priority and 7 represents the lowest priority.
-
- The sender and recipient SHOULD use best-effort to process streams in
- the order of highest priority to lowest priority.
-
-2.3.4. Stream headers
-
- Streams carry optional sets of name/value pair headers which carry
- metadata about the stream. After the stream has been created, and as
- long as the sender is not closed (Section 2.3.7) or half-closed
- (Section 2.3.6), each side may send HEADERS frame(s) containing the
- header data. Header data can be sent in multiple HEADERS frames, and
- HEADERS frames may be interleaved with data frames.
-
-2.3.5. Stream data exchange
-
- Once a stream is created, it can be used to send arbitrary amounts of
- data. Generally this means that a series of data frames will be sent
- on the stream until a frame containing the FLAG_FIN flag is set. The
- FLAG_FIN can be set on a SYN_STREAM (Section 2.6.1), SYN_REPLY
- (Section 2.6.2), HEADERS (Section 2.6.7) or a DATA (Section 2.2.2)
- frame. Once the FLAG_FIN has been sent, the stream is considered to
- be half-closed.
-
-2.3.6. Stream half-close
-
- When one side of the stream sends a frame with the FLAG_FIN flag set,
- the stream is half-closed from that endpoint. The sender of the
- FLAG_FIN MUST NOT send further frames on that stream. When both
- sides have half-closed, the stream is closed.
-
- If an endpoint receives a data frame after the stream is half-closed
- from the sender (e.g. the endpoint has already received a prior frame
- for the stream with the FIN flag set), it MUST send a RST_STREAM to
- the sender with the status STREAM_ALREADY_CLOSED.
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 10]
-
-Internet-Draft SPDY Feb 2012
-
-
-2.3.7. Stream close
-
- There are 3 ways that streams can be terminated:
-
- Normal termination: Normal stream termination occurs when both
- sender and recipient have half-closed the stream by sending a
- FLAG_FIN.
-
- Abrupt termination: Either the client or server can send a
- RST_STREAM control frame at any time. A RST_STREAM contains an
- error code to indicate the reason for failure. When a RST_STREAM
- is sent from the stream originator, it indicates a failure to
- complete the stream and that no further data will be sent on the
- stream. When a RST_STREAM is sent from the stream recipient, the
- sender, upon receipt, should stop sending any data on the stream.
- The stream recipient should be aware that there is a race between
- data already in transit from the sender and the time the
- RST_STREAM is received. See Stream Error Handling (Section 2.4.2)
-
- TCP connection teardown: If the TCP connection is torn down while
- un-closed streams exist, then the endpoint must assume that the
- stream was abnormally interrupted and may be incomplete.
-
- If an endpoint receives a data frame after the stream is closed, it
- must send a RST_STREAM to the sender with the status PROTOCOL_ERROR.
-
-2.4. Error Handling
-
- The SPDY framing layer has only two types of errors, and they are
- always handled consistently. Any reference in this specification to
- "issue a session error" refers to Section 2.4.1. Any reference to
- "issue a stream error" refers to Section 2.4.2.
-
-2.4.1. Session Error Handling
-
- A session error is any error which prevents further processing of the
- framing layer or which corrupts the session compression state. When
- a session error occurs, the endpoint encountering the error MUST
- first send a GOAWAY (Section 2.6.6) frame with the stream id of most
- recently received stream from the remote endpoint, and the error code
- for why the session is terminating. After sending the GOAWAY frame,
- the endpoint MUST close the TCP connection.
-
- Note that the session compression state is dependent upon both
- endpoints always processing all compressed data. If an endpoint
- partially processes a frame containing compressed data without
- updating compression state properly, future control frames which use
- compression will be always be errored. Implementations SHOULD always
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 11]
-
-Internet-Draft SPDY Feb 2012
-
-
- try to process compressed data so that errors which could be handled
- as stream errors do not become session errors.
-
- Note that because this GOAWAY is sent during a session error case, it
- is possible that the GOAWAY will not be reliably received by the
- receiving endpoint. It is a best-effort attempt to communicate with
- the remote about why the session is going down.
-
-2.4.2. Stream Error Handling
-
- A stream error is an error related to a specific stream-id which does
- not affect processing of other streams at the framing layer. Upon a
- stream error, the endpoint MUST send a RST_STREAM (Section 2.6.3)
- frame which contains the stream id of the stream where the error
- occurred and the error status which caused the error. After sending
- the RST_STREAM, the stream is closed to the sending endpoint. After
- sending the RST_STREAM, if the sender receives any frames other than
- a RST_STREAM for that stream id, it will result in sending additional
- RST_STREAM frames. An endpoint MUST NOT send a RST_STREAM in
- response to an RST_STREAM, as doing so would lead to RST_STREAM
- loops. Sending a RST_STREAM does not cause the SPDY session to be
- closed.
-
- If an endpoint has multiple RST_STREAM frames to send in succession
- for the same stream-id and the same error code, it MAY coalesce them
- into a single RST_STREAM frame. (This can happen if a stream is
- closed, but the remote sends multiple data frames. There is no
- reason to send a RST_STREAM for each frame in succession).
-
-2.5. Data flow
-
- Because TCP provides a single stream of data on which SPDY
- multiplexes multiple logical streams, clients and servers must
- intelligently interleave data messages for concurrent sessions.
-
-2.6. Control frame types
-
-2.6.1. SYN_STREAM
-
- The SYN_STREAM control frame allows the sender to asynchronously
- create a stream between the endpoints. See Stream Creation
- (Section 2.3.2)
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 12]
-
-Internet-Draft SPDY Feb 2012
-
-
-+------------------------------------+
-|1| version | 1 |
-+------------------------------------+
-| Flags (8) | Length (24 bits) |
-+------------------------------------+
-|X| Stream-ID (31bits) |
-+------------------------------------+
-|X| Associated-To-Stream-ID (31bits) |
-+------------------------------------+
-| Pri|Unused | Slot | |
-+-------------------+ |
-| Number of Name/Value pairs (int32) | <+
-+------------------------------------+ |
-| Length of name (int32) | | This section is the "Name/Value
-+------------------------------------+ | Header Block", and is compressed.
-| Name (string) | |
-+------------------------------------+ |
-| Length of value (int32) | |
-+------------------------------------+ |
-| Value (string) | |
-+------------------------------------+ |
-| (repeats) | <+
-
- Flags: Flags related to this frame. Valid flags are:
-
- 0x01 = FLAG_FIN - marks this frame as the last frame to be
- transmitted on this stream and puts the sender in the half-closed
- (Section 2.3.6) state.
-
- 0x02 = FLAG_UNIDIRECTIONAL - a stream created with this flag puts
- the recipient in the half-closed (Section 2.3.6) state.
-
- Length: The length is the number of bytes which follow the length
- field in the frame. For SYN_STREAM frames, this is 10 bytes plus the
- length of the compressed Name/Value block.
-
- Stream-ID: The 31-bit identifier for this stream. This stream-id
- will be used in frames which are part of this stream.
-
- Associated-To-Stream-ID: The 31-bit identifier for a stream which
- this stream is associated to. If this stream is independent of all
- other streams, it should be 0.
-
- Priority: A 3-bit priority (Section 2.3.3) field.
-
- Unused: 5 bits of unused space, reserved for future use.
-
- Slot: An 8 bit unsigned integer specifying the index in the server's
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 13]
-
-Internet-Draft SPDY Feb 2012
-
-
- CREDENTIAL vector of the client certificate to be used for this
- request. see CREDENTIAL frame (Section 2.6.9). The value 0 means no
- client certificate should be associated with this stream.
-
- Name/Value Header Block: A set of name/value pairs carried as part of
- the SYN_STREAM. see Name/Value Header Block (Section 2.6.10).
-
- If an endpoint receives a SYN_STREAM which is larger than the
- implementation supports, it MAY send a RST_STREAM with error code
- FRAME_TOO_LARGE. All implementations MUST support the minimum size
- limits defined in the Control Frames section (Section 2.2.1).
-
-2.6.2. SYN_REPLY
-
- SYN_REPLY indicates the acceptance of a stream creation by the
- recipient of a SYN_STREAM frame.
-
-+------------------------------------+
-|1| version | 2 |
-+------------------------------------+
-| Flags (8) | Length (24 bits) |
-+------------------------------------+
-|X| Stream-ID (31bits) |
-+------------------------------------+
-| Number of Name/Value pairs (int32) | <+
-+------------------------------------+ |
-| Length of name (int32) | | This section is the "Name/Value
-+------------------------------------+ | Header Block", and is compressed.
-| Name (string) | |
-+------------------------------------+ |
-| Length of value (int32) | |
-+------------------------------------+ |
-| Value (string) | |
-+------------------------------------+ |
-| (repeats) | <+
-
- Flags: Flags related to this frame. Valid flags are:
-
- 0x01 = FLAG_FIN - marks this frame as the last frame to be
- transmitted on this stream and puts the sender in the half-closed
- (Section 2.3.6) state.
-
- Length: The length is the number of bytes which follow the length
- field in the frame. For SYN_REPLY frames, this is 4 bytes plus the
- length of the compressed Name/Value block.
-
- Stream-ID: The 31-bit identifier for this stream.
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 14]
-
-Internet-Draft SPDY Feb 2012
-
-
- If an endpoint receives multiple SYN_REPLY frames for the same active
- stream ID, it MUST issue a stream error (Section 2.4.2) with the
- error code STREAM_IN_USE.
-
- Name/Value Header Block: A set of name/value pairs carried as part of
- the SYN_STREAM. see Name/Value Header Block (Section 2.6.10).
-
- If an endpoint receives a SYN_REPLY which is larger than the
- implementation supports, it MAY send a RST_STREAM with error code
- FRAME_TOO_LARGE. All implementations MUST support the minimum size
- limits defined in the Control Frames section (Section 2.2.1).
-
-2.6.3. RST_STREAM
-
- The RST_STREAM frame allows for abnormal termination of a stream.
- When sent by the creator of a stream, it indicates the creator wishes
- to cancel the stream. When sent by the recipient of a stream, it
- indicates an error or that the recipient did not want to accept the
- stream, so the stream should be closed.
-
- +----------------------------------+
- |1| version | 3 |
- +----------------------------------+
- | Flags (8) | 8 |
- +----------------------------------+
- |X| Stream-ID (31bits) |
- +----------------------------------+
- | Status code |
- +----------------------------------+
-
- Flags: Flags related to this frame. RST_STREAM does not define any
- flags. This value must be 0.
-
- Length: An unsigned 24-bit value representing the number of bytes
- after the length field. For RST_STREAM control frames, this value is
- always 8.
-
- Stream-ID: The 31-bit identifier for this stream.
-
- Status code: (32 bits) An indicator for why the stream is being
- terminated.The following status codes are defined:
-
- 1 - PROTOCOL_ERROR. This is a generic error, and should only be
- used if a more specific error is not available.
-
- 2 - INVALID_STREAM. This is returned when a frame is received for
- a stream which is not active.
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 15]
-
-Internet-Draft SPDY Feb 2012
-
-
- 3 - REFUSED_STREAM. Indicates that the stream was refused before
- any processing has been done on the stream.
-
- 4 - UNSUPPORTED_VERSION. Indicates that the recipient of a stream
- does not support the SPDY version requested.
-
- 5 - CANCEL. Used by the creator of a stream to indicate that the
- stream is no longer needed.
-
- 6 - INTERNAL_ERROR. This is a generic error which can be used
- when the implementation has internally failed, not due to anything
- in the protocol.
-
- 7 - FLOW_CONTROL_ERROR. The endpoint detected that its peer
- violated the flow control protocol.
-
- 8 - STREAM_IN_USE. The endpoint received a SYN_REPLY for a stream
- already open.
-
- 9 - STREAM_ALREADY_CLOSED. The endpoint received a data or
- SYN_REPLY frame for a stream which is half closed.
-
- 10 - INVALID_CREDENTIALS. The server received a request for a
- resource whose origin does not have valid credentials in the
- client certificate vector.
-
- 11 - FRAME_TOO_LARGE. The endpoint received a frame which this
- implementation could not support. If FRAME_TOO_LARGE is sent for
- a SYN_STREAM, HEADERS, or SYN_REPLY frame without fully processing
- the compressed portion of those frames, then the compression state
- will be out-of-sync with the other endpoint. In this case,
- senders of FRAME_TOO_LARGE MUST close the session.
-
- Note: 0 is not a valid status code for a RST_STREAM.
-
- After receiving a RST_STREAM on a stream, the recipient must not send
- additional frames for that stream, and the stream moves into the
- closed state.
-
-2.6.4. SETTINGS
-
- A SETTINGS frame contains a set of id/value pairs for communicating
- configuration data about how the two endpoints may communicate.
- SETTINGS frames can be sent at any time by either endpoint, are
- optionally sent, and are fully asynchronous. When the server is the
- sender, the sender can request that configuration data be persisted
- by the client across SPDY sessions and returned to the server in
- future communications.
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 16]
-
-Internet-Draft SPDY Feb 2012
-
-
- Persistence of SETTINGS ID/Value pairs is done on a per origin/IP
- pair (the "origin" is the set of scheme, host, and port from the URI.
- See [RFC6454]). That is, when a client connects to a server, and the
- server persists settings within the client, the client SHOULD return
- the persisted settings on future connections to the same origin AND
- IP address and TCP port. Clients MUST NOT request servers to use the
- persistence features of the SETTINGS frames, and servers MUST ignore
- persistence related flags sent by a client.
-
- +----------------------------------+
- |1| version | 4 |
- +----------------------------------+
- | Flags (8) | Length (24 bits) |
- +----------------------------------+
- | Number of entries |
- +----------------------------------+
- | ID/Value Pairs |
- | ... |
-
- Control bit: The control bit is always 1 for this message.
-
- Version: The SPDY version number.
-
- Type: The message type for a SETTINGS message is 4.
-
- Flags: FLAG_SETTINGS_CLEAR_SETTINGS (0x1): When set, the client
- should clear any previously persisted SETTINGS ID/Value pairs. If
- this frame contains ID/Value pairs with the
- FLAG_SETTINGS_PERSIST_VALUE set, then the client will first clear its
- existing, persisted settings, and then persist the values with the
- flag set which are contained within this frame. Because persistence
- is only implemented on the client, this flag can only be used when
- the sender is the server.
-
- Length: An unsigned 24-bit value representing the number of bytes
- after the length field. The total size of a SETTINGS frame is 8
- bytes + length.
-
- Number of entries: A 32-bit value representing the number of ID/value
- pairs in this message.
-
- ID: A 32-bit ID number, comprised of 8 bits of flags and 24 bits of
- unique ID.
-
- ID.flags:
-
- FLAG_SETTINGS_PERSIST_VALUE (0x1): When set, the sender of this
- SETTINGS frame is requesting that the recipient persist the ID/
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 17]
-
-Internet-Draft SPDY Feb 2012
-
-
- Value and return it in future SETTINGS frames sent from the
- sender to this recipient. Because persistence is only
- implemented on the client, this flag is only sent by the
- server.
-
- FLAG_SETTINGS_PERSISTED (0x2): When set, the sender is
- notifying the recipient that this ID/Value pair was previously
- sent to the sender by the recipient with the
- FLAG_SETTINGS_PERSIST_VALUE, and the sender is returning it.
- Because persistence is only implemented on the client, this
- flag is only sent by the client.
-
- Defined IDs:
-
- 1 - SETTINGS_UPLOAD_BANDWIDTH allows the sender to send its
- expected upload bandwidth on this channel. This number is an
- estimate. The value should be the integral number of kilobytes
- per second that the sender predicts as an expected maximum
- upload channel capacity.
-
- 2 - SETTINGS_DOWNLOAD_BANDWIDTH allows the sender to send its
- expected download bandwidth on this channel. This number is an
- estimate. The value should be the integral number of kilobytes
- per second that the sender predicts as an expected maximum
- download channel capacity.
-
- 3 - SETTINGS_ROUND_TRIP_TIME allows the sender to send its
- expected round-trip-time on this channel. The round trip time
- is defined as the minimum amount of time to send a control
- frame from this client to the remote and receive a response.
- The value is represented in milliseconds.
-
- 4 - SETTINGS_MAX_CONCURRENT_STREAMS allows the sender to inform
- the remote endpoint the maximum number of concurrent streams
- which it will allow. By default there is no limit. For
- implementors it is recommended that this value be no smaller
- than 100.
-
- 5 - SETTINGS_CURRENT_CWND allows the sender to inform the
- remote endpoint of the current TCP CWND value.
-
- 6 - SETTINGS_DOWNLOAD_RETRANS_RATE allows the sender to inform
- the remote endpoint the retransmission rate (bytes
- retransmitted / total bytes transmitted).
-
- 7 - SETTINGS_INITIAL_WINDOW_SIZE allows the sender to inform
- the remote endpoint the initial window size (in bytes) for new
- streams.
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 18]
-
-Internet-Draft SPDY Feb 2012
-
-
- 8 - SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE allows the server
- to inform the client if the new size of the client certificate
- vector.
-
- Value: A 32-bit value.
-
- The message is intentionally extensible for future information which
- may improve client-server communications. The sender does not need
- to send every type of ID/value. It must only send those for which it
- has accurate values to convey. When multiple ID/value pairs are
- sent, they should be sent in order of lowest id to highest id. A
- single SETTINGS frame MUST not contain multiple values for the same
- ID. If the recipient of a SETTINGS frame discovers multiple values
- for the same ID, it MUST ignore all values except the first one.
-
- A server may send multiple SETTINGS frames containing different ID/
- Value pairs. When the same ID/Value is sent twice, the most recent
- value overrides any previously sent values. If the server sends IDs
- 1, 2, and 3 with the FLAG_SETTINGS_PERSIST_VALUE in a first SETTINGS
- frame, and then sends IDs 4 and 5 with the
- FLAG_SETTINGS_PERSIST_VALUE, when the client returns the persisted
- state on its next SETTINGS frame, it SHOULD send all 5 settings (1,
- 2, 3, 4, and 5 in this example) to the server.
-
-2.6.5. PING
-
- The PING control frame is a mechanism for measuring a minimal round-
- trip time from the sender. It can be sent from the client or the
- server. Recipients of a PING frame should send an identical frame to
- the sender as soon as possible (if there is other pending data
- waiting to be sent, PING should take highest priority). Each ping
- sent by a sender should use a unique ID.
-
- +----------------------------------+
- |1| version | 6 |
- +----------------------------------+
- | 0 (flags) | 4 (length) |
- +----------------------------------|
- | 32-bit ID |
- +----------------------------------+
-
- Control bit: The control bit is always 1 for this message.
-
- Version: The SPDY version number.
-
- Type: The message type for a PING message is 6.
-
- Length: This frame is always 4 bytes long.
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 19]
-
-Internet-Draft SPDY Feb 2012
-
-
- ID: A unique ID for this ping, represented as an unsigned 32 bit
- value. When the client initiates a ping, it must use an odd numbered
- ID. When the server initiates a ping, it must use an even numbered
- ping. Use of odd/even IDs is required in order to avoid accidental
- looping on PINGs (where each side initiates an identical PING at the
- same time).
-
- Note: If a sender uses all possible PING ids (e.g. has sent all 2^31
- possible IDs), it can wrap and start re-using IDs.
-
- If a server receives an even numbered PING which it did not initiate,
- it must ignore the PING. If a client receives an odd numbered PING
- which it did not initiate, it must ignore the PING.
-
-2.6.6. GOAWAY
-
- The GOAWAY control frame is a mechanism to tell the remote side of
- the connection to stop creating streams on this session. It can be
- sent from the client or the server. Once sent, the sender will not
- respond to any new SYN_STREAMs on this session. Recipients of a
- GOAWAY frame must not send additional streams on this session,
- although a new session can be established for new streams. The
- purpose of this message is to allow an endpoint to gracefully stop
- accepting new streams (perhaps for a reboot or maintenance), while
- still finishing processing of previously established streams.
-
- There is an inherent race condition between an endpoint sending
- SYN_STREAMs and the remote sending a GOAWAY message. To deal with
- this case, the GOAWAY contains a last-stream-id indicating the
- stream-id of the last stream which was created on the sending
- endpoint in this session. If the receiver of the GOAWAY sent new
- SYN_STREAMs for sessions after this last-stream-id, they were not
- processed by the server and the receiver may treat the stream as
- though it had never been created at all (hence the receiver may want
- to re-create the stream later on a new session).
-
- Endpoints should always send a GOAWAY message before closing a
- connection so that the remote can know whether a stream has been
- partially processed or not. (For example, if an HTTP client sends a
- POST at the same time that a server closes a connection, the client
- cannot know if the server started to process that POST request if the
- server does not send a GOAWAY frame to indicate where it stopped
- working).
-
- After sending a GOAWAY message, the sender must ignore all SYN_STREAM
- frames for new streams.
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 20]
-
-Internet-Draft SPDY Feb 2012
-
-
- +----------------------------------+
- |1| version | 7 |
- +----------------------------------+
- | 0 (flags) | 8 (length) |
- +----------------------------------|
- |X| Last-good-stream-ID (31 bits) |
- +----------------------------------+
- | Status code |
- +----------------------------------+
-
- Control bit: The control bit is always 1 for this message.
-
- Version: The SPDY version number.
-
- Type: The message type for a GOAWAY message is 7.
-
- Length: This frame is always 8 bytes long.
-
- Last-good-stream-Id: The last stream id which was replied to (with
- either a SYN_REPLY or RST_STREAM) by the sender of the GOAWAY
- message. If no streams were replied to, this value MUST be 0.
-
- Status: The reason for closing the session.
-
- 0 - OK. This is a normal session teardown.
-
- 1 - PROTOCOL_ERROR. This is a generic error, and should only be
- used if a more specific error is not available.
-
- 11 - INTERNAL_ERROR. This is a generic error which can be used
- when the implementation has internally failed, not due to anything
- in the protocol.
-
-2.6.7. HEADERS
-
- The HEADERS frame augments a stream with additional headers. It may
- be optionally sent on an existing stream at any time. Specific
- application of the headers in this frame is application-dependent.
- The name/value header block within this frame is compressed.
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 21]
-
-Internet-Draft SPDY Feb 2012
-
-
-+------------------------------------+
-|1| version | 8 |
-+------------------------------------+
-| Flags (8) | Length (24 bits) |
-+------------------------------------+
-|X| Stream-ID (31bits) |
-+------------------------------------+
-| Number of Name/Value pairs (int32) | <+
-+------------------------------------+ |
-| Length of name (int32) | | This section is the "Name/Value
-+------------------------------------+ | Header Block", and is compressed.
-| Name (string) | |
-+------------------------------------+ |
-| Length of value (int32) | |
-+------------------------------------+ |
-| Value (string) | |
-+------------------------------------+ |
-| (repeats) | <+
-
- Flags: Flags related to this frame. Valid flags are:
-
- 0x01 = FLAG_FIN - marks this frame as the last frame to be
- transmitted on this stream and puts the sender in the half-closed
- (Section 2.3.6) state.
-
- Length: An unsigned 24 bit value representing the number of bytes
- after the length field. The minimum length of the length field is 4
- (when the number of name value pairs is 0).
-
- Stream-ID: The stream this HEADERS block is associated with.
-
- Name/Value Header Block: A set of name/value pairs carried as part of
- the SYN_STREAM. see Name/Value Header Block (Section 2.6.10).
-
-2.6.8. WINDOW_UPDATE
-
- The WINDOW_UPDATE control frame is used to implement per stream flow
- control in SPDY. Flow control in SPDY is per hop, that is, only
- between the two endpoints of a SPDY connection. If there are one or
- more intermediaries between the client and the origin server, flow
- control signals are not explicitly forwarded by the intermediaries.
- (However, throttling of data transfer by any recipient may have the
- effect of indirectly propagating flow control information upstream
- back to the original sender.) Flow control only applies to the data
- portion of data frames. Recipients must buffer all control frames.
- If a recipient fails to buffer an entire control frame, it MUST issue
- a stream error (Section 2.4.2) with the status code
- FLOW_CONTROL_ERROR for the stream.
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 22]
-
-Internet-Draft SPDY Feb 2012
-
-
- Flow control in SPDY is implemented by a data transfer window kept by
- the sender of each stream. The data transfer window is a simple
- uint32 that indicates how many bytes of data the sender can transmit.
- After a stream is created, but before any data frames have been
- transmitted, the sender begins with the initial window size. This
- window size is a measure of the buffering capability of the
- recipient. The sender must not send a data frame with data length
- greater than the transfer window size. After sending each data
- frame, the sender decrements its transfer window size by the amount
- of data transmitted. When the window size becomes less than or equal
- to 0, the sender must pause transmitting data frames. At the other
- end of the stream, the recipient sends a WINDOW_UPDATE control back
- to notify the sender that it has consumed some data and freed up
- buffer space to receive more data.
-
- +----------------------------------+
- |1| version | 9 |
- +----------------------------------+
- | 0 (flags) | 8 (length) |
- +----------------------------------+
- |X| Stream-ID (31-bits) |
- +----------------------------------+
- |X| Delta-Window-Size (31-bits) |
- +----------------------------------+
-
- Control bit: The control bit is always 1 for this message.
-
- Version: The SPDY version number.
-
- Type: The message type for a WINDOW_UPDATE message is 9.
-
- Length: The length field is always 8 for this frame (there are 8
- bytes after the length field).
-
- Stream-ID: The stream ID that this WINDOW_UPDATE control frame is
- for.
-
- Delta-Window-Size: The additional number of bytes that the sender can
- transmit in addition to existing remaining window size. The legal
- range for this field is 1 to 2^31 - 1 (0x7fffffff) bytes.
-
- The window size as kept by the sender must never exceed 2^31
- (although it can become negative in one special case). If a sender
- receives a WINDOW_UPDATE that causes the its window size to exceed
- this limit, it must send RST_STREAM with status code
- FLOW_CONTROL_ERROR to terminate the stream.
-
- When a SPDY connection is first established, the default initial
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 23]
-
-Internet-Draft SPDY Feb 2012
-
-
- window size for all streams is 64KB. An endpoint can use the
- SETTINGS control frame to adjust the initial window size for the
- connection. That is, its peer can start out using the 64KB default
- initial window size when sending data frames before receiving the
- SETTINGS. Because SETTINGS is asynchronous, there may be a race
- condition if the recipient wants to decrease the initial window size,
- but its peer immediately sends 64KB on the creation of a new
- connection, before waiting for the SETTINGS to arrive. This is one
- case where the window size kept by the sender will become negative.
- Once the sender detects this condition, it must stop sending data
- frames and wait for the recipient to catch up. The recipient has two
- choices:
-
- immediately send RST_STREAM with FLOW_CONTROL_ERROR status code.
-
- allow the head of line blocking (as there is only one stream for
- the session and the amount of data in flight is bounded by the
- default initial window size), and send WINDOW_UPDATE as it
- consumes data.
-
- In the case of option 2, both sides must compute the window size
- based on the initial window size in the SETTINGS. For example, if
- the recipient sets the initial window size to be 16KB, and the sender
- sends 64KB immediately on connection establishment, the sender will
- discover its window size is -48KB on receipt of the SETTINGS. As the
- recipient consumes the first 16KB, it must send a WINDOW_UPDATE of
- 16KB back to the sender. This interaction continues until the
- sender's window size becomes positive again, and it can resume
- transmitting data frames.
-
- After the recipient reads in a data frame with FLAG_FIN that marks
- the end of the data stream, it should not send WINDOW_UPDATE frames
- as it consumes the last data frame. A sender should ignore all the
- WINDOW_UPDATE frames associated with the stream after it send the
- last frame for the stream.
-
- The data frames from the sender and the WINDOW_UPDATE frames from the
- recipient are completely asynchronous with respect to each other.
- This property allows a recipient to aggressively update the window
- size kept by the sender to prevent the stream from stalling.
-
-2.6.9. CREDENTIAL
-
- The CREDENTIAL control frame is used by the client to send additional
- client certificates to the server. A SPDY client may decide to send
- requests for resources from different origins on the same SPDY
- session if it decides that that server handles both origins. For
- example if the IP address associated with both hostnames matches and
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 24]
-
-Internet-Draft SPDY Feb 2012
-
-
- the SSL server certificate presented in the initial handshake is
- valid for both hostnames. However, because the SSL connection can
- contain at most one client certificate, the client needs a mechanism
- to send additional client certificates to the server.
-
- The server is required to maintain a vector of client certificates
- associated with a SPDY session. When the client needs to send a
- client certificate to the server, it will send a CREDENTIAL frame
- that specifies the index of the slot in which to store the
- certificate as well as proof that the client posesses the
- corresponding private key. The initial size of this vector must be
- 8. If the client provides a client certificate during the first TLS
- handshake, the contents of this certificate must be copied into the
- first slot (index 1) in the CREDENTIAL vector, though it may be
- overwritten by subsequent CREDENTIAL frames. The server must
- exclusively use the CREDNETIAL vector when evaluating the client
- certificates associated with an origin. The server may change the
- size of this vector by sending a SETTINGS frame with the setting
- SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE value specified. In the
- event that the new size is smaller than the current size, truncation
- occurs preserving lower-index slots as possible.
-
- TLS renegotiation with client authentication is incompatible with
- SPDY given the multiplexed nature of SPDY. Specifically, imagine
- that the client has 2 requests outstanding to the server for two
- different pages (in different tabs). When the renegotiation + client
- certificate request comes in, the browser is unable to determine
- which resource triggered the client certificate request, in order to
- prompt the user accordingly.
-
- +----------------------------------+
- |1|000000000000001|0000000000001011|
- +----------------------------------+
- | flags (8) | Length (24 bits) |
- +----------------------------------+
- | Slot (16 bits) | |
- +-----------------+ |
- | Proof Length (32 bits) |
- +----------------------------------+
- | Proof |
- +----------------------------------+ <+
- | Certificate Length (32 bits) | |
- +----------------------------------+ | Repeated until end of frame
- | Certificate | |
- +----------------------------------+ <+
-
- Slot: The index in the server's client certificate vector where this
- certificate should be stored. If there is already a certificate
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 25]
-
-Internet-Draft SPDY Feb 2012
-
-
- stored at this index, it will be overwritten. The index is one
- based, not zero based; zero is an invalid slot index.
-
- Proof: Cryptographic proof that the client has possession of the
- private key associated with the certificate. The format is a TLS
- digitally-signed element
- (http://tools.ietf.org/html/rfc5246#section-4.7). The signature
- algorithm must be the same as that used in the CertificateVerify
- message. However, since the MD5+SHA1 signature type used in TLS 1.0
- connections can not be correctly encoded in a digitally-signed
- element, SHA1 must be used when MD5+SHA1 was used in the SSL
- connection. The signature is calculated over a 32 byte TLS extractor
- value (http://tools.ietf.org/html/rfc5705) with a label of "EXPORTER
- SPDY certificate proof" using the empty string as context. ForRSA
- certificates the signature would be a PKCS#1 v1.5 signature. For
- ECDSA, it would be an ECDSA-Sig-Value
- (http://tools.ietf.org/html/rfc5480#appendix-A). For a 1024-bit RSA
- key, the CREDENTIAL message would be ~500 bytes.
-
- Certificate: The certificate chain, starting with the leaf
- certificate. Each certificate must be encoded as a 32 bit length,
- followed by a DER encoded certificate. The certificate must be of
- the same type (RSA, ECDSA, etc) as the client certificate associated
- with the SSL connection.
-
- If the server receives a request for a resource with unacceptable
- credential (either missing or invalid), it must reply with a
- RST_STREAM frame with the status code INVALID_CREDENTIALS. Upon
- receipt of a RST_STREAM frame with INVALID_CREDENTIALS, the client
- should initiate a new stream directly to the requested origin and
- resend the request. Note, SPDY does not allow the server to request
- different client authentication for different resources in the same
- origin.
-
- If the server receives an invalid CREDENTIAL frame, it MUST respond
- with a GOAWAY frame and shutdown the session.
-
-2.6.10. Name/Value Header Block
-
- The Name/Value Header Block is found in the SYN_STREAM, SYN_REPLY and
- HEADERS control frames, and shares a common format:
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 26]
-
-Internet-Draft SPDY Feb 2012
-
-
- +------------------------------------+
- | Number of Name/Value pairs (int32) |
- +------------------------------------+
- | Length of name (int32) |
- +------------------------------------+
- | Name (string) |
- +------------------------------------+
- | Length of value (int32) |
- +------------------------------------+
- | Value (string) |
- +------------------------------------+
- | (repeats) |
-
- Number of Name/Value pairs: The number of repeating name/value pairs
- following this field.
-
- List of Name/Value pairs:
-
- Length of Name: a 32-bit value containing the number of octets in
- the name field. Note that in practice, this length must not
- exceed 2^24, as that is the maximum size of a SPDY frame.
-
- Name: 0 or more octets, 8-bit sequences of data, excluding 0.
-
- Length of Value: a 32-bit value containing the number of octets in
- the value field. Note that in practice, this length must not
- exceed 2^24, as that is the maximum size of a SPDY frame.
-
- Value: 0 or more octets, 8-bit sequences of data, excluding 0.
-
- Each header name must have at least one value. Header names are
- encoded using the US-ASCII character set [ASCII] and must be all
- lower case. The length of each name must be greater than zero. A
- recipient of a zero-length name MUST issue a stream error
- (Section 2.4.2) with the status code PROTOCOL_ERROR for the
- stream-id.
-
- Duplicate header names are not allowed. To send two identically
- named headers, send a header with two values, where the values are
- separated by a single NUL (0) byte. A header value can either be
- empty (e.g. the length is zero) or it can contain multiple, NUL-
- separated values, each with length greater than zero. The value
- never starts nor ends with a NUL character. Recipients of illegal
- value fields MUST issue a stream error (Section 2.4.2) with the
- status code PROTOCOL_ERROR for the stream-id.
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 27]
-
-Internet-Draft SPDY Feb 2012
-
-
-2.6.10.1. Compression
-
- The Name/Value Header Block is a section of the SYN_STREAM,
- SYN_REPLY, and HEADERS frames used to carry header meta-data. This
- block is always compressed using zlib compression. Within this
- specification, any reference to 'zlib' is referring to the ZLIB
- Compressed Data Format Specification Version 3.3 as part of RFC1950.
- [RFC1950]
-
- For each HEADERS compression instance, the initial state is
- initialized using the following dictionary [UDELCOMPRESSION]:
-
- const unsigned char SPDY_dictionary_txt[] = {
- 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, \\ - - - - o p t i
- 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, \\ o n s - - - - h
- 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, \\ e a d - - - - p
- 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, \\ o s t - - - - p
- 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, \\ u t - - - - d e
- 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, \\ l e t e - - - -
- 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, \\ t r a c e - - -
- 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, \\ - a c c e p t -
- 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, \\ - - - a c c e p
- 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, \\ t - c h a r s e
- 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, \\ t - - - - a c c
- 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, \\ e p t - e n c o
- 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, \\ d i n g - - - -
- 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, \\ a c c e p t - l
- 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, \\ a n g u a g e -
- 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, \\ - - - a c c e p
- 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, \\ t - r a n g e s
- 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, \\ - - - - a g e -
- 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, \\ - - - a l l o w
- 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, \\ - - - - a u t h
- 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, \\ o r i z a t i o
- 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, \\ n - - - - c a c
- 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, \\ h e - c o n t r
- 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, \\ o l - - - - c o
- 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, \\ n n e c t i o n
- 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, \\ - - - - c o n t
- 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, \\ e n t - b a s e
- 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, \\ - - - - c o n t
- 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, \\ e n t - e n c o
- 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, \\ d i n g - - - -
- 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, \\ c o n t e n t -
- 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, \\ l a n g u a g e
- 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, \\ - - - - c o n t
- 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, \\ e n t - l e n g
- 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, \\ t h - - - - c o
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 28]
-
-Internet-Draft SPDY Feb 2012
-
-
- 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, \\ n t e n t - l o
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, \\ c a t i o n - -
- 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \\ - - c o n t e n
- 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, \\ t - m d 5 - - -
- 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, \\ - c o n t e n t
- 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, \\ - r a n g e - -
- 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \\ - - c o n t e n
- 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, \\ t - t y p e - -
- 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, \\ - - d a t e - -
- 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, \\ - - e t a g - -
- 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, \\ - - e x p e c t
- 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, \\ - - - - e x p i
- 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, \\ r e s - - - - f
- 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, \\ r o m - - - - h
- 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, \\ o s t - - - - i
- 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, \\ f - m a t c h -
- 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, \\ - - - i f - m o
- 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, \\ d i f i e d - s
- 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, \\ i n c e - - - -
- 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, \\ i f - n o n e -
- 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, \\ m a t c h - - -
- 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, \\ - i f - r a n g
- 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, \\ e - - - - i f -
- 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, \\ u n m o d i f i
- 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, \\ e d - s i n c e
- 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, \\ - - - - l a s t
- 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, \\ - m o d i f i e
- 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, \\ d - - - - l o c
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, \\ a t i o n - - -
- 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, \\ - m a x - f o r
- 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, \\ w a r d s - - -
- 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, \\ - p r a g m a -
- 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, \\ - - - p r o x y
- 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, \\ - a u t h e n t
- 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, \\ i c a t e - - -
- 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, \\ - p r o x y - a
- 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, \\ u t h o r i z a
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, \\ t i o n - - - -
- 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, \\ r a n g e - - -
- 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, \\ - r e f e r e r
- 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, \\ - - - - r e t r
- 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, \\ y - a f t e r -
- 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, \\ - - - s e r v e
- 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, \\ r - - - - t e -
- 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, \\ - - - t r a i l
- 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, \\ e r - - - - t r
- 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, \\ a n s f e r - e
- 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, \\ n c o d i n g -
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 29]
-
-Internet-Draft SPDY Feb 2012
-
-
- 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, \\ - - - u p g r a
- 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, \\ d e - - - - u s
- 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, \\ e r - a g e n t
- 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, \\ - - - - v a r y
- 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, \\ - - - - v i a -
- 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, \\ - - - w a r n i
- 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, \\ n g - - - - w w
- 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, \\ w - a u t h e n
- 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, \\ t i c a t e - -
- 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, \\ - - m e t h o d
- 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, \\ - - - - g e t -
- 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, \\ - - - s t a t u
- 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, \\ s - - - - 2 0 0
- 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, \\ - O K - - - - v
- 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, \\ e r s i o n - -
- 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, \\ - - H T T P - 1
- 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, \\ - 1 - - - - u r
- 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, \\ l - - - - p u b
- 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, \\ l i c - - - - s
- 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, \\ e t - c o o k i
- 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, \\ e - - - - k e e
- 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, \\ p - a l i v e -
- 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, \\ - - - o r i g i
- 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, \\ n 1 0 0 1 0 1 2
- 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, \\ 0 1 2 0 2 2 0 5
- 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, \\ 2 0 6 3 0 0 3 0
- 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, \\ 2 3 0 3 3 0 4 3
- 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, \\ 0 5 3 0 6 3 0 7
- 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, \\ 4 0 2 4 0 5 4 0
- 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, \\ 6 4 0 7 4 0 8 4
- 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, \\ 0 9 4 1 0 4 1 1
- 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, \\ 4 1 2 4 1 3 4 1
- 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, \\ 4 4 1 5 4 1 6 4
- 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, \\ 1 7 5 0 2 5 0 4
- 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, \\ 5 0 5 2 0 3 - N
- 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, \\ o n - A u t h o
- 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, \\ r i t a t i v e
- 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, \\ - I n f o r m a
- 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, \\ t i o n 2 0 4 -
- 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, \\ N o - C o n t e
- 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, \\ n t 3 0 1 - M o
- 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, \\ v e d - P e r m
- 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, \\ a n e n t l y 4
- 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, \\ 0 0 - B a d - R
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, \\ e q u e s t 4 0
- 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, \\ 1 - U n a u t h
- 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, \\ o r i z e d 4 0
- 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, \\ 3 - F o r b i d
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 30]
-
-Internet-Draft SPDY Feb 2012
-
-
- 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, \\ d e n 4 0 4 - N
- 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, \\ o t - F o u n d
- 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, \\ 5 0 0 - I n t e
- 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, \\ r n a l - S e r
- 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, \\ v e r - E r r o
- 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, \\ r 5 0 1 - N o t
- 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, \\ - I m p l e m e
- 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, \\ n t e d 5 0 3 -
- 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, \\ S e r v i c e -
- 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, \\ U n a v a i l a
- 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, \\ b l e J a n - F
- 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, \\ e b - M a r - A
- 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, \\ p r - M a y - J
- 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, \\ u n - J u l - A
- 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, \\ u g - S e p t -
- 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, \\ O c t - N o v -
- 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, \\ D e c - 0 0 - 0
- 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, \\ 0 - 0 0 - M o n
- 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, \\ - - T u e - - W
- 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, \\ e d - - T h u -
- 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, \\ - F r i - - S a
- 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, \\ t - - S u n - -
- 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, \\ G M T c h u n k
- 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, \\ e d - t e x t -
- 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, \\ h t m l - i m a
- 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, \\ g e - p n g - i
- 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, \\ m a g e - j p g
- 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, \\ - i m a g e - g
- 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, \\ i f - a p p l i
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, \\ c a t i o n - x
- 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, \\ m l - a p p l i
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, \\ c a t i o n - x
- 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, \\ h t m l - x m l
- 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, \\ - t e x t - p l
- 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, \\ a i n - t e x t
- 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, \\ - j a v a s c r
- 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, \\ i p t - p u b l
- 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, \\ i c p r i v a t
- 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, \\ e m a x - a g e
- 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, \\ - g z i p - d e
- 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, \\ f l a t e - s d
- 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, \\ c h c h a r s e
- 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, \\ t - u t f - 8 c
- 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, \\ h a r s e t - i
- 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, \\ s o - 8 8 5 9 -
- 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, \\ 1 - u t f - - -
- 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e \\ - e n q - 0 -
- };
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 31]
-
-Internet-Draft SPDY Feb 2012
-
-
- The entire contents of the name/value header block is compressed
- using zlib. There is a single zlib stream for all name value pairs
- in one direction on a connection. SPDY uses a SYNC_FLUSH between
- each compressed frame.
-
- Implementation notes: the compression engine can be tuned to favor
- speed or size. Optimizing for size increases memory use and CPU
- consumption. Because header blocks are generally small, implementors
- may want to reduce the window-size of the compression engine from the
- default 15bits (a 32KB window) to more like 11bits (a 2KB window).
- The exact setting is chosen by the compressor, the decompressor will
- work with any setting.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 32]
-
-Internet-Draft SPDY Feb 2012
-
-
-3. HTTP Layering over SPDY
-
- SPDY is intended to be as compatible as possible with current web-
- based applications. This means that, from the perspective of the
- server business logic or application API, the features of HTTP are
- unchanged. To achieve this, all of the application request and
- response header semantics are preserved, although the syntax of
- conveying those semantics has changed. Thus, the rules from the
- HTTP/1.1 specification in RFC2616 [RFC2616] apply with the changes in
- the sections below.
-
-3.1. Connection Management
-
- Clients SHOULD NOT open more than one SPDY session to a given origin
- [RFC6454] concurrently.
-
- Note that it is possible for one SPDY session to be finishing (e.g. a
- GOAWAY message has been sent, but not all streams have finished),
- while another SPDY session is starting.
-
-3.1.1. Use of GOAWAY
-
- SPDY provides a GOAWAY message which can be used when closing a
- connection from either the client or server. Without a server GOAWAY
- message, HTTP has a race condition where the client sends a request
- (a new SYN_STREAM) just as the server is closing the connection, and
- the client cannot know if the server received the stream or not. By
- using the last-stream-id in the GOAWAY, servers can indicate to the
- client if a request was processed or not.
-
- Note that some servers will choose to send the GOAWAY and immediately
- terminate the connection without waiting for active streams to
- finish. The client will be able to determine this because SPDY
- streams are determinstically closed. This abrupt termination will
- force the client to heuristically decide whether to retry the pending
- requests. Clients always need to be capable of dealing with this
- case because they must deal with accidental connection termination
- cases, which are the same as the server never having sent a GOAWAY.
-
- More sophisticated servers will use GOAWAY to implement a graceful
- teardown. They will send the GOAWAY and provide some time for the
- active streams to finish before terminating the connection.
-
- If a SPDY client closes the connection, it should also send a GOAWAY
- message. This allows the server to know if any server-push streams
- were received by the client.
-
- If the endpoint closing the connection has not received any
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 33]
-
-Internet-Draft SPDY Feb 2012
-
-
- SYN_STREAMs from the remote, the GOAWAY will contain a last-stream-id
- of 0.
-
-3.2. HTTP Request/Response
-
-3.2.1. Request
-
- The client initiates a request by sending a SYN_STREAM frame. For
- requests which do not contain a body, the SYN_STREAM frame MUST set
- the FLAG_FIN, indicating that the client intends to send no further
- data on this stream. For requests which do contain a body, the
- SYN_STREAM will not contain the FLAG_FIN, and the body will follow
- the SYN_STREAM in a series of DATA frames. The last DATA frame will
- set the FLAG_FIN to indicate the end of the body.
-
- The SYN_STREAM Name/Value section will contain all of the HTTP
- headers which are associated with an HTTP request. The header block
- in SPDY is mostly unchanged from today's HTTP header block, with the
- following differences:
-
- The first line of the request is unfolded into name/value pairs
- like other HTTP headers and MUST be present:
-
- ":method" - the HTTP method for this request (e.g. "GET",
- "POST", "HEAD", etc)
-
- ":path" - the url-path for this url with "/" prefixed. (See
- RFC1738 [RFC1738]). For example, for
- "http://www.google.com/search?q=dogs" the path would be
- "/search?q=dogs".
-
- ":version" - the HTTP version of this request (e.g.
- "HTTP/1.1")
-
- In addition, the following two name/value pairs must also be
- present in every request:
-
- ":host" - the hostport (See RFC1738 [RFC1738]) portion of the
- URL for this request (e.g. "www.google.com:1234"). This header
- is the same as the HTTP 'Host' header.
-
- ":scheme" - the scheme portion of the URL for this request
- (e.g. "https"))
-
- Header names are all lowercase.
-
- The Connection, Host, Keep-Alive, Proxy-Connection, and Transfer-
- Encoding headers are not valid and MUST not be sent.
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 34]
-
-Internet-Draft SPDY Feb 2012
-
-
- User-agents MUST support gzip compression. Regardless of the
- Accept-Encoding sent by the user-agent, the server may always send
- content encoded with gzip or deflate encoding.
-
- If a server receives a request where the sum of the data frame
- payload lengths does not equal the size of the Content-Length
- header, the server MUST return a 400 (Bad Request) error.
-
- POST-specific changes:
-
- Although POSTs are inherently chunked, POST requests SHOULD
- also be accompanied by a Content-Length header. There are two
- reasons for this: First, it assists with upload progress meters
- for an improved user experience. But second, we know from
- early versions of SPDY that failure to send a content length
- header is incompatible with many existing HTTP server
- implementations. Existing user-agents do not omit the Content-
- Length header, and server implementations have come to depend
- upon this.
-
- The user-agent is free to prioritize requests as it sees fit. If the
- user-agent cannot make progress without receiving a resource, it
- should attempt to raise the priority of that resource. Resources
- such as images, SHOULD generally use the lowest priority.
-
- If a client sends a SYN_STREAM without all of the method, host, path,
- scheme, and version headers, the server MUST reply with a HTTP 400
- Bad Request reply.
-
-3.2.2. Response
-
- The server responds to a client request with a SYN_REPLY frame.
- Symmetric to the client's upload stream, server will send data after
- the SYN_REPLY frame via a series of DATA frames, and the last data
- frame will contain the FLAG_FIN to indicate successful end-of-stream.
- If a response (like a 202 or 204 response) contains no body, the
- SYN_REPLY frame may contain the FLAG_FIN flag to indicate no further
- data will be sent on the stream.
-
- The response status line is unfolded into name/value pairs like
- other HTTP headers and must be present:
-
- ":status" - The HTTP response status code (e.g. "200" or "200
- OK")
-
- ":version" - The HTTP response version (e.g. "HTTP/1.1")
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 35]
-
-Internet-Draft SPDY Feb 2012
-
-
- All header names must be lowercase.
-
- The Connection, Keep-Alive, Proxy-Connection, and Transfer-
- Encoding headers are not valid and MUST not be sent.
-
- Responses MAY be accompanied by a Content-Length header for
- advisory purposes. (e.g. for UI progress meters)
-
- If a client receives a response where the sum of the data frame
- payload lengths does not equal the size of the Content-Length
- header, the client MUST ignore the content length header.
-
- If a client receives a SYN_REPLY without a status or without a
- version header, the client must reply with a RST_STREAM frame
- indicating a PROTOCOL ERROR.
-
-3.2.3. Authentication
-
- When a client sends a request to an origin server that requires
- authentication, the server can reply with a "401 Unauthorized"
- response, and include a WWW-Authenticate challenge header that
- defines the authentication scheme to be used. The client then
- retries the request with an Authorization header appropriate to the
- specified authentication scheme.
-
- There are four options for proxy authentication, Basic, Digest, NTLM
- and Negotiate (SPNEGO). The first two options were defined in
- RFC2617 [RFC2617], and are stateless. The second two options were
- developed by Microsoft and specified in RFC4559 [RFC4559], and are
- stateful; otherwise known as multi-round authentication, or
- connection authentication.
-
-3.2.3.1. Stateless Authentication
-
- Stateless Authentication over SPDY is identical to how it is
- performed over HTTP. If multiple SPDY streams are concurrently sent
- to a single server, each will authenticate independently, similar to
- how two HTTP connections would independently authenticate to a proxy
- server.
-
-3.2.3.2. Stateful Authentication
-
- Unfortunately, the stateful authentication mechanisms were
- implemented and defined in a such a way that directly violates
- RFC2617 - they do not include a "realm" as part of the request. This
- is problematic in SPDY because it makes it impossible for a client to
- disambiguate two concurrent server authentication challenges.
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 36]
-
-Internet-Draft SPDY Feb 2012
-
-
- To deal with this case, SPDY servers using Stateful Authentication
- MUST implement one of two changes:
-
- Servers can add a "realm=<desired realm>" header so that the two
- authentication requests can be disambiguated and run concurrently.
- Unfortunately, given how these mechanisms work, this is probably
- not practical.
-
- Upon sending the first stateful challenge response, the server
- MUST buffer and defer all further frames which are not part of
- completing the challenge until the challenge has completed.
- Completing the authentication challenge may take multiple round
- trips. Once the client receives a "401 Authenticate" response for
- a stateful authentication type, it MUST stop sending new requests
- to the server until the authentication has completed by receiving
- a non-401 response on at least one stream.
-
-3.3. Server Push Transactions
-
- SPDY enables a server to send multiple replies to a client for a
- single request. The rationale for this feature is that sometimes a
- server knows that it will need to send multiple resources in response
- to a single request. Without server push features, the client must
- first download the primary resource, then discover the secondary
- resource(s), and request them. Pushing of resources avoids the
- round-trip delay, but also creates a potential race where a server
- can be pushing content which a user-agent is in the process of
- requesting. The following mechanics attempt to prevent the race
- condition while enabling the performance benefit.
-
- Browsers receiving a pushed response MUST validate that the server is
- authorized to push the URL using the browser same-origin [RFC6454]
- policy. For example, a SPDY connection to www.foo.com is generally
- not permitted to push a response for www.evil.com.
-
- If the browser accepts a pushed response (e.g. it does not send a
- RST_STREAM), the browser MUST attempt to cache the pushed response in
- same way that it would cache any other response. This means
- validating the response headers and inserting into the disk cache.
-
- Because pushed responses have no request, they have no request
- headers associated with them. At the framing layer, SPDY pushed
- streams contain an "associated-stream-id" which indicates the
- requested stream for which the pushed stream is related. The pushed
- stream inherits all of the headers from the associated-stream-id with
- the exception of ":host", ":scheme", and ":path", which are provided
- as part of the pushed response stream headers. The browser MUST
- store these inherited and implied request headers with the cached
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 37]
-
-Internet-Draft SPDY Feb 2012
-
-
- resource.
-
- Implementation note: With server push, it is theoretically possible
- for servers to push unreasonable amounts of content or resources to
- the user-agent. Browsers MUST implement throttles to protect against
- unreasonable push attacks.
-
-3.3.1. Server implementation
-
- When the server intends to push a resource to the user-agent, it
- opens a new stream by sending a unidirectional SYN_STREAM. The
- SYN_STREAM MUST include an Associated-To-Stream-ID, and MUST set the
- FLAG_UNIDIRECTIONAL flag. The SYN_STREAM MUST include headers for
- ":scheme", ":host", ":path", which represent the URL for the resource
- being pushed. Subsequent headers may follow in HEADERS frames. The
- purpose of the association is so that the user-agent can
- differentiate which request induced the pushed stream; without it, if
- the user-agent had two tabs open to the same page, each pushing
- unique content under a fixed URL, the user-agent would not be able to
- differentiate the requests.
-
- The Associated-To-Stream-ID must be the ID of an existing, open
- stream. The reason for this restriction is to have a clear endpoint
- for pushed content. If the user-agent requested a resource on stream
- 11, the server replies on stream 11. It can push any number of
- additional streams to the client before sending a FLAG_FIN on stream
- 11. However, once the originating stream is closed no further push
- streams may be associated with it. The pushed streams do not need to
- be closed (FIN set) before the originating stream is closed, they
- only need to be created before the originating stream closes.
-
- It is illegal for a server to push a resource with the Associated-To-
- Stream-ID of 0.
-
- To minimize race conditions with the client, the SYN_STREAM for the
- pushed resources MUST be sent prior to sending any content which
- could allow the client to discover the pushed resource and request
- it.
-
- The server MUST only push resources which would have been returned
- from a GET request.
-
- Note: If the server does not have all of the Name/Value Response
- headers available at the time it issues the HEADERS frame for the
- pushed resource, it may later use an additional HEADERS frame to
- augment the name/value pairs to be associated with the pushed stream.
- The subsequent HEADERS frame(s) must not contain a header for
- ':host', ':scheme', or ':path' (e.g. the server can't change the
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 38]
-
-Internet-Draft SPDY Feb 2012
-
-
- identity of the resource to be pushed). The HEADERS frame must not
- contain duplicate headers with a previously sent HEADERS frame. The
- server must send a HEADERS frame including the scheme/host/port
- headers before sending any data frames on the stream.
-
-3.3.2. Client implementation
-
- When fetching a resource the client has 3 possibilities:
-
- the resource is not being pushed
-
- the resource is being pushed, but the data has not yet arrived
-
- the resource is being pushed, and the data has started to arrive
-
- When a SYN_STREAM and HEADERS frame which contains an Associated-To-
- Stream-ID is received, the client must not issue GET requests for the
- resource in the pushed stream, and instead wait for the pushed stream
- to arrive.
-
- If a client receives a server push stream with stream-id 0, it MUST
- issue a session error (Section 2.4.1) with the status code
- PROTOCOL_ERROR.
-
- When a client receives a SYN_STREAM from the server without a the
- ':host', ':scheme', and ':path' headers in the Name/Value section, it
- MUST reply with a RST_STREAM with error code HTTP_PROTOCOL_ERROR.
-
- To cancel individual server push streams, the client can issue a
- stream error (Section 2.4.2) with error code CANCEL. Upon receipt,
- the server MUST stop sending on this stream immediately (this is an
- Abrupt termination).
-
- To cancel all server push streams related to a request, the client
- may issue a stream error (Section 2.4.2) with error code CANCEL on
- the associated-stream-id. By cancelling that stream, the server MUST
- immediately stop sending frames for any streams with
- in-association-to for the original stream.
-
- If the server sends a HEADER frame containing duplicate headers with
- a previous HEADERS frame for the same stream, the client must issue a
- stream error (Section 2.4.2) with error code PROTOCOL ERROR.
-
- If the server sends a HEADERS frame after sending a data frame for
- the same stream, the client MAY ignore the HEADERS frame. Ignoring
- the HEADERS frame after a data frame prevents handling of HTTP's
- trailing headers
- (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.40).
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 39]
-
-Internet-Draft SPDY Feb 2012
-
-
-4. Design Rationale and Notes
-
- Authors' notes: The notes in this section have no bearing on the SPDY
- protocol as specified within this document, and none of these notes
- should be considered authoritative about how the protocol works.
- However, these notes may prove useful in future debates about how to
- resolve protocol ambiguities or how to evolve the protocol going
- forward. They may be removed before the final draft.
-
-4.1. Separation of Framing Layer and Application Layer
-
- Readers may note that this specification sometimes blends the framing
- layer (Section 2) with requirements of a specific application - HTTP
- (Section 3). This is reflected in the request/response nature of the
- streams, the definition of the HEADERS and compression contexts which
- are very similar to HTTP, and other areas as well.
-
- This blending is intentional - the primary goal of this protocol is
- to create a low-latency protocol for use with HTTP. Isolating the
- two layers is convenient for description of the protocol and how it
- relates to existing HTTP implementations. However, the ability to
- reuse the SPDY framing layer is a non goal.
-
-4.2. Error handling - Framing Layer
-
- Error handling at the SPDY layer splits errors into two groups: Those
- that affect an individual SPDY stream, and those that do not.
-
- When an error is confined to a single stream, but general framing is
- in tact, SPDY attempts to use the RST_STREAM as a mechanism to
- invalidate the stream but move forward without aborting the
- connection altogether.
-
- For errors occuring outside of a single stream context, SPDY assumes
- the entire session is hosed. In this case, the endpoint detecting
- the error should initiate a connection close.
-
-4.3. One Connection Per Domain
-
- SPDY attempts to use fewer connections than other protocols have
- traditionally used. The rationale for this behavior is because it is
- very difficult to provide a consistent level of service (e.g. TCP
- slow-start), prioritization, or optimal compression when the client
- is connecting to the server through multiple channels.
-
- Through lab measurements, we have seen consistent latency benefits by
- using fewer connections from the client. The overall number of
- packets sent by SPDY can be as much as 40% less than HTTP. Handling
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 40]
-
-Internet-Draft SPDY Feb 2012
-
-
- large numbers of concurrent connections on the server also does
- become a scalability problem, and SPDY reduces this load.
-
- The use of multiple connections is not without benefit, however.
- Because SPDY multiplexes multiple, independent streams onto a single
- stream, it creates a potential for head-of-line blocking problems at
- the transport level. In tests so far, the negative effects of head-
- of-line blocking (especially in the presence of packet loss) is
- outweighed by the benefits of compression and prioritization.
-
-4.4. Fixed vs Variable Length Fields
-
- SPDY favors use of fixed length 32bit fields in cases where smaller,
- variable length encodings could have been used. To some, this seems
- like a tragic waste of bandwidth. SPDY choses the simple encoding
- for speed and simplicity.
-
- The goal of SPDY is to reduce latency on the network. The overhead
- of SPDY frames is generally quite low. Each data frame is only an 8
- byte overhead for a 1452 byte payload (~0.6%). At the time of this
- writing, bandwidth is already plentiful, and there is a strong trend
- indicating that bandwidth will continue to increase. With an average
- worldwide bandwidth of 1Mbps, and assuming that a variable length
- encoding could reduce the overhead by 50%, the latency saved by using
- a variable length encoding would be less than 100 nanoseconds. More
- interesting are the effects when the larger encodings force a packet
- boundary, in which case a round-trip could be induced. However, by
- addressing other aspects of SPDY and TCP interactions, we believe
- this is completely mitigated.
-
-4.5. Compression Context(s)
-
- When isolating the compression contexts used for communicating with
- multiple origins, we had a few choices to make. We could have
- maintained a map (or list) of compression contexts usable for each
- origin. The basic case is easy - each HEADERS frame would need to
- identify the context to use for that frame. However, compression
- contexts are not cheap, so the lifecycle of each context would need
- to be bounded. For proxy servers, where we could churn through many
- contexts, this would be a concern. We considered using a static set
- of contexts, say 16 of them, which would bound the memory use. We
- also considered dynamic contexts, which could be created on the fly,
- and would need to be subsequently destroyed. All of these are
- complicated, and ultimately we decided that such a mechanism creates
- too many problems to solve.
-
- Alternatively, we've chosen the simple approach, which is to simply
- provide a flag for resetting the compression context. For the common
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 41]
-
-Internet-Draft SPDY Feb 2012
-
-
- case (no proxy), this fine because most requests are to the same
- origin and we never need to reset the context. For cases where we
- are using two different origins over a single SPDY session, we simply
- reset the compression state between each transition.
-
-4.6. Unidirectional streams
-
- Many readers notice that unidirectional streams are both a bit
- confusing in concept and also somewhat redundant. If the recipient
- of a stream doesn't wish to send data on a stream, it could simply
- send a SYN_REPLY with the FLAG_FIN bit set. The FLAG_UNIDIRECTIONAL
- is, therefore, not necessary.
-
- It is true that we don't need the UNIDIRECTIONAL markings. It is
- added because it avoids the recipient of pushed streams from needing
- to send a set of empty frames (e.g. the SYN_STREAM w/ FLAG_FIN) which
- otherwise serve no purpose.
-
-4.7. Data Compression
-
- Generic compression of data portion of the streams (as opposed to
- compression of the headers) without knowing the content of the stream
- is redundant. There is no value in compressing a stream which is
- already compressed. Because of this, SPDY does allow data
- compression to be optional. We included it because study of existing
- websites shows that many sites are not using compression as they
- should, and users suffer because of it. We wanted a mechanism where,
- at the SPDY layer, site administrators could simply force compression
- - it is better to compress twice than to not compress.
-
- Overall, however, with this feature being optional and sometimes
- redundant, it is unclear if it is useful at all. We will likely
- remove it from the specification.
-
-4.8. Server Push
-
- A subtle but important point is that server push streams must be
- declared before the associated stream is closed. The reason for this
- is so that proxies have a lifetime for which they can discard
- information about previous streams. If a pushed stream could
- associate itself with an already-closed stream, then endpoints would
- not have a specific lifecycle for when they could disavow knowledge
- of the streams which went before.
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 42]
-
-Internet-Draft SPDY Feb 2012
-
-
-5. Security Considerations
-
-5.1. Use of Same-origin constraints
-
- This specification uses the same-origin policy [RFC6454] in all cases
- where verification of content is required.
-
-5.2. HTTP Headers and SPDY Headers
-
- At the application level, HTTP uses name/value pairs in its headers.
- Because SPDY merges the existing HTTP headers with SPDY headers,
- there is a possibility that some HTTP applications already use a
- particular header name. To avoid any conflicts, all headers
- introduced for layering HTTP over SPDY are prefixed with ":". ":" is
- not a valid sequence in HTTP header naming, preventing any possible
- conflict.
-
-5.3. Cross-Protocol Attacks
-
- By utilizing TLS, we believe that SPDY introduces no new cross-
- protocol attacks. TLS encrypts the contents of all transmission
- (except the handshake itself), making it difficult for attackers to
- control the data which could be used in a cross-protocol attack.
-
-5.4. Server Push Implicit Headers
-
- Pushed resources do not have an associated request. In order for
- existing HTTP cache control validations (such as the Vary header) to
- work, however, all cached resources must have a set of request
- headers. For this reason, browsers MUST be careful to inherit
- request headers from the associated stream for the push. This
- includes the 'Cookie' header.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 43]
-
-Internet-Draft SPDY Feb 2012
-
-
-6. Privacy Considerations
-
-6.1. Long Lived Connections
-
- SPDY aims to keep connections open longer between clients and servers
- in order to reduce the latency when a user makes a request. The
- maintenance of these connections over time could be used to expose
- private information. For example, a user using a browser hours after
- the previous user stopped using that browser may be able to learn
- about what the previous user was doing. This is a problem with HTTP
- in its current form as well, however the short lived connections make
- it less of a risk.
-
-6.2. SETTINGS frame
-
- The SPDY SETTINGS frame allows servers to store out-of-band
- transmitted information about the communication between client and
- server on the client. Although this is intended only to be used to
- reduce latency, renegade servers could use it as a mechanism to store
- identifying information about the client in future requests.
-
- Clients implementing privacy modes, such as Google Chrome's
- "incognito mode", may wish to disable client-persisted SETTINGS
- storage.
-
- Clients MUST clear persisted SETTINGS information when clearing the
- cookies.
-
- TODO: Put range maximums on each type of setting to limit
- inappropriate uses.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 44]
-
-Internet-Draft SPDY Feb 2012
-
-
-7. Incompatibilities with SPDY draft #2
-
- Here is a list of the major changes between this draft and draft #2.
-
- Addition of flow control
-
- Increased 16 bit length fields in SYN_STREAM and SYN_REPLY to 32
- bits.
-
- Changed definition of compression for DATA frames
-
- Updated compression dictionary
-
- Fixed off-by-one on the compression dictionary for headers
-
- Increased priority field from 2bits to 3bits.
-
- Removed NOOP frame
-
- Split the request "url" into "scheme", "host", and "path"
-
- Added the requirement that POSTs contain content-length.
-
- Removed wasted 16bits of unused space from the end of the
- SYN_REPLY and HEADERS frames.
-
- Fixed bug: Priorities were described backward (0 was lowest
- instead of highest).
-
- Fixed bug: Name/Value header counts were duplicated in both the
- Name Value header block and also the containing frame.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 45]
-
-Internet-Draft SPDY Feb 2012
-
-
-8. Requirements Notation
-
- The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
- "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
- document are to be interpreted as described in RFC 2119 [RFC2119].
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 46]
-
-Internet-Draft SPDY Feb 2012
-
-
-9. Acknowledgements
-
- Many individuals have contributed to the design and evolution of
- SPDY: Adam Langley, Wan-Teh Chang, Jim Morrison, Mark Nottingham,
- Alyssa Wilk, Costin Manolache, William Chan, Vitaliy Lvin, Joe Chan,
- Adam Barth, Ryan Hamilton, Gavin Peters, Kent Alstad, Kevin Lindsay,
- Paul Amer, Fan Yang, Jonathan Leighton
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 47]
-
-Internet-Draft SPDY Feb 2012
-
-
-10. Normative References
-
- [RFC0793] Postel, J., "Transmission Control Protocol", STD 7,
- RFC 793, September 1981.
-
- [RFC1738] Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform
- Resource Locators (URL)", RFC 1738, December 1994.
-
- [RFC1950] Deutsch, L. and J-L. Gailly, "ZLIB Compressed Data Format
- Specification version 3.3", RFC 1950, May 1996.
-
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
- Requirement Levels", BCP 14, RFC 2119, March 1997.
-
- [RFC2285] Mandeville, R., "Benchmarking Terminology for LAN
- Switching Devices", RFC 2285, February 1998.
-
- [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
- Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
- Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
-
- [RFC2617] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S.,
- Leach, P., Luotonen, A., and L. Stewart, "HTTP
- Authentication: Basic and Digest Access Authentication",
- RFC 2617, June 1999.
-
- [RFC4559] Jaganathan, K., Zhu, L., and J. Brezak, "SPNEGO-based
- Kerberos and NTLM HTTP Authentication in Microsoft
- Windows", RFC 4559, June 2006.
-
- [RFC4366] Blake-Wilson, S., Nystrom, M., Hopwood, D., Mikkelsen, J.,
- and T. Wright, "Transport Layer Security (TLS)
- Extensions", RFC 4366, April 2006.
-
- [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
- (TLS) Protocol Version 1.2", RFC 5246, August 2008.
-
- [RFC6454] Barth, A., "The Web Origin Concept", RFC 6454,
- December 2011.
-
- [TLSNPN] Langley, A., "TLS Next Protocol Negotiation",
- <http://tools.ietf.org/html/
- draft-agl-tls-nextprotoneg-01>.
-
- [ASCII] "US-ASCII. Coded Character Set - 7-Bit American Standard
- Code for Information Interchange. Standard ANSI X3.4-1986,
- ANSI, 1986.".
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 48]
-
-Internet-Draft SPDY Feb 2012
-
-
- [UDELCOMPRESSION]
- Yang, F., Amer, P., and J. Leighton, "A Methodology to
- Derive SPDY's Initial Dictionary for Zlib Compression",
- <http://www.eecis.udel.edu/~amer/PEL/poc/pdf/
- SPDY-Fan.pdf>.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 49]
-
-Internet-Draft SPDY Feb 2012
-
-
-Appendix A. Changes
-
- To be removed by RFC Editor before publication
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 50]
-
-Internet-Draft SPDY Feb 2012
-
-
-Authors' Addresses
-
- Mike Belshe
- Twist
-
- Email: address@hidden
-
-
- Roberto Peon
- Google, Inc
-
- Email: address@hidden
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Belshe & Peon Expires August 4, 2012 [Page 51]
-
Modified: libmicrohttpd/src/examples/Makefile.am
===================================================================
--- libmicrohttpd/src/examples/Makefile.am 2015-12-01 10:19:37 UTC (rev
36707)
+++ libmicrohttpd/src/examples/Makefile.am 2015-12-01 13:06:38 UTC (rev
36708)
@@ -13,18 +13,7 @@
AM_CFLAGS += --coverage
endif
-if ENABLE_SPDY
-spdyex = \
- spdy_event_loop \
- spdy_fileserver \
- spdy_response_with_callback
-if HAVE_SPDYLAY
-spdyex += mhd2spdy
-endif
-endif
-
-
# example programs
noinst_PROGRAMS = \
benchmark \
@@ -37,8 +26,7 @@
fileserver_example \
fileserver_example_dirs \
fileserver_example_external_select \
- refuse_post_example \
- $(spdyex)
+ refuse_post_example
if ENABLE_HTTPS
@@ -98,15 +86,6 @@
$(top_builddir)/src/microhttpd/libmicrohttpd.la \
$(PTHREAD_LIBS) -lmagic
-mhd2spdy_SOURCES = \
- mhd2spdy.c \
- mhd2spdy_spdy.c mhd2spdy_spdy.h \
- mhd2spdy_http.c mhd2spdy_http.h \
- mhd2spdy_structures.c mhd2spdy_structures.h
-mhd2spdy_LDADD = \
- $(top_builddir)/src/microhttpd/libmicrohttpd.la \
- -lssl -lcrypto -lspdylay
-
benchmark_SOURCES = \
benchmark.c
benchmark_CPPFLAGS = \
@@ -179,20 +158,3 @@
$(top_builddir)/src/microhttpd/libmicrohttpd.la
-spdy_event_loop_SOURCES = \
- spdy_event_loop.c
-spdy_event_loop_LDADD = \
- $(top_builddir)/src/microspdy/libmicrospdy.la \
- -lz
-
-spdy_fileserver_SOURCES = \
- spdy_fileserver.c
-spdy_fileserver_LDADD = \
- $(top_builddir)/src/microspdy/libmicrospdy.la \
- -lz
-
-spdy_response_with_callback_SOURCES = \
- spdy_response_with_callback.c
-spdy_response_with_callback_LDADD = \
- $(top_builddir)/src/microspdy/libmicrospdy.la \
- -lz
Deleted: libmicrohttpd/src/examples/mhd2spdy.c
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy.c 2015-12-01 10:19:37 UTC (rev
36707)
+++ libmicrohttpd/src/examples/mhd2spdy.c 2015-12-01 13:06:38 UTC (rev
36708)
@@ -1,322 +0,0 @@
-/*
- Copyright Copyright (C) 2013 Andrey Uzunov
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file mhd2spdy.c
- * @brief The main file of the HTTP-to-SPDY proxy with the 'main' function
- * and event loop. No threads are used.
- * Currently only GET is supported.
- * TODOs:
- * - non blocking SSL connect
- * - check certificate
- * - on closing spdy session, close sockets for all requests
- * @author Andrey Uzunov
- */
-
-
-#include "mhd2spdy_structures.h"
-#include "mhd2spdy_spdy.h"
-#include "mhd2spdy_http.h"
-
-
-static int run = 1;
-//static int spdy_close = 0;
-
-
-static void
-catch_signal(int signal)
-{
- (void)signal;
- //spdy_close = 1;
- run = 0;
-}
-
-
-void
-print_stat()
-{
- if(!glob_opt.statistics)
- return;
-
- printf("--------------------------\n");
- printf("Statistics (TLS overhead is ignored when used):\n");
- //printf("HTTP bytes received: %lld\n", glob_stat.http_bytes_received);
- //printf("HTTP bytes sent: %lld\n", glob_stat.http_bytes_sent);
- printf("SPDY bytes sent: %lld\n", glob_stat.spdy_bytes_sent);
- printf("SPDY bytes received: %lld\n", glob_stat.spdy_bytes_received);
- printf("SPDY bytes received and dropped: %lld\n",
glob_stat.spdy_bytes_received_and_dropped);
-}
-
-
-int
-run_everything ()
-{
- unsigned long long timeoutlong=0;
- struct timeval timeout;
- int ret;
- fd_set rs;
- fd_set ws;
- fd_set es;
- int maxfd = -1;
- int maxfd_s = -1;
- struct MHD_Daemon *daemon;
- nfds_t spdy_npollfds = 1;
- struct URI * spdy2http_uri = NULL;
- struct SPDY_Connection *connection;
- struct SPDY_Connection *connections[MAX_SPDY_CONNECTIONS];
- struct SPDY_Connection *connection_for_delete;
-
- if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
- PRINT_INFO("signal failed");
-
- if (signal(SIGINT, catch_signal) == SIG_ERR)
- PRINT_INFO("signal failed");
-
- glob_opt.streams_opened = 0;
- glob_opt.responses_pending = 0;
- //glob_opt.global_memory = 0;
-
- srand(time(NULL));
-
- if(init_parse_uri(&glob_opt.uri_preg))
- DIE("Regexp compilation failed");
-
- if(NULL != glob_opt.spdy2http_str)
- {
- ret = parse_uri(&glob_opt.uri_preg, glob_opt.spdy2http_str,
&spdy2http_uri);
- if(ret != 0)
- DIE("spdy_parse_uri failed");
- }
-
- SSL_load_error_strings();
- SSL_library_init();
- glob_opt.ssl_ctx = SSL_CTX_new(SSLv23_client_method());
- if(glob_opt.ssl_ctx == NULL) {
- PRINT_INFO2("SSL_CTX_new %s", ERR_error_string(ERR_get_error(), NULL));
- abort();
- }
- spdy_ssl_init_ssl_ctx(glob_opt.ssl_ctx, &glob_opt.spdy_proto_version);
-
- daemon = MHD_start_daemon (
- MHD_SUPPRESS_DATE_NO_CLOCK,
- glob_opt.listen_port,
- NULL, NULL, &http_cb_request, NULL,
- MHD_OPTION_URI_LOG_CALLBACK, &http_cb_log, NULL,
- MHD_OPTION_NOTIFY_COMPLETED, &http_cb_request_completed, NULL,
- MHD_OPTION_END);
- if(NULL==daemon)
- DIE("MHD_start_daemon failed");
-
- do
- {
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
-
- if(NULL == glob_opt.spdy_connection && NULL != glob_opt.spdy2http_str)
- {
- glob_opt.spdy_connection = spdy_connect(spdy2http_uri,
spdy2http_uri->port, strcmp("https", spdy2http_uri->scheme)==0);
- if(NULL == glob_opt.spdy_connection && glob_opt.only_proxy)
- PRINT_INFO("cannot connect to the proxy");
- }
-
- FD_ZERO(&rs);
- FD_ZERO(&ws);
- FD_ZERO(&es);
-
- ret = MHD_get_timeout(daemon, &timeoutlong);
- if(MHD_NO == ret || timeoutlong > 5000)
- timeout.tv_sec = 5;
- else
- {
- timeout.tv_sec = timeoutlong / 1000;
- timeout.tv_usec = (timeoutlong % 1000) * 1000;
- }
-
- if(MHD_NO == MHD_get_fdset (daemon,
- &rs,
- &ws,
- &es,
- &maxfd))
- {
- PRINT_INFO("MHD_get_fdset error");
- }
- assert(-1 != maxfd);
-
- maxfd_s = spdy_get_selectfdset(
- &rs,
- &ws,
- &es,
- connections, MAX_SPDY_CONNECTIONS,
&spdy_npollfds);
- if(maxfd_s > maxfd)
- maxfd = maxfd_s;
-
- PRINT_INFO2("MHD timeout %lld %lld", (unsigned long long)timeout.tv_sec,
(unsigned long long)timeout.tv_usec);
-
- glob_opt.spdy_data_received = false;
-
- ret = select(maxfd+1, &rs, &ws, &es, &timeout);
- PRINT_INFO2("timeout now %lld %lld ret is %i", (unsigned long
long)timeout.tv_sec, (unsigned long long)timeout.tv_usec, ret);
-
- switch(ret)
- {
- case -1:
- PRINT_INFO2("select error: %i", errno);
- break;
- case 0:
- //break;
- default:
- PRINT_INFO("run");
- //MHD_run_from_select(daemon,&rs, &ws, &es); //not closing FDs at some
time in past
- MHD_run(daemon);
- spdy_run_select(&rs, &ws, &es, connections, spdy_npollfds);
- if(glob_opt.spdy_data_received)
- {
- PRINT_INFO("MHD run again");
- //MHD_run_from_select(daemon,&rs, &ws, &es); //not closing FDs at
some time in past
- MHD_run(daemon);
- }
- break;
- }
- }
- while(run);
-
- MHD_stop_daemon (daemon);
-
- //TODO SSL_free brakes
- spdy_free_connection(glob_opt.spdy_connection);
-
- connection = glob_opt.spdy_connections_head;
- while(NULL != connection)
- {
- connection_for_delete = connection;
- connection = connection_for_delete->next;
- glob_opt.streams_opened -= connection_for_delete->streams_opened;
- DLL_remove(glob_opt.spdy_connections_head, glob_opt.spdy_connections_tail,
connection_for_delete);
- spdy_free_connection(connection_for_delete);
- }
-
- free_uri(spdy2http_uri);
-
- deinit_parse_uri(&glob_opt.uri_preg);
-
- SSL_CTX_free(glob_opt.ssl_ctx);
- ERR_free_strings();
- EVP_cleanup();
-
- PRINT_INFO2("spdy streams: %i; http requests: %i", glob_opt.streams_opened,
glob_opt.responses_pending);
- //PRINT_INFO2("memory allocated %zu bytes", glob_opt.global_memory);
-
- print_stat();
-
- return 0;
-}
-
-
-void
-display_usage()
-{
- printf(
- "Usage: mhd2spdy [-ovs] [-b <SPDY2HTTP-PROXY>] -p <PORT>\n\n"
- "OPTIONS:\n"
- " -p, --port Listening port.\n"
- " -b, --backend-proxy If set, he proxy will send requests to\n"
- " that SPDY server or proxy. Set the address\n"
- " in the form 'http://host:port'. Use 'https'\n"
- " for SPDY over TLS, or 'http' for plain SPDY\n"
- " communication with the backend.\n"
- " -o, --only-proxy If set, the proxy will always forward the\n"
- " requests to the backend proxy. If not set,\n"
- " the proxy will first try to establsh SPDY\n"
- " connection to the requested server. If the\n"
- " server does not support SPDY and TLS, the\n"
- " backend proxy will be used for the request.\n"
- " -v, --verbose Print debug information.\n"
- " -s, --statistics Print simple statistics on exit.\n\n"
-
- );
-}
-
-
-int
-main (int argc,
- char *const *argv)
-{
- int getopt_ret;
- int option_index;
- struct option long_options[] = {
- {"port", required_argument, 0, 'p'},
- {"backend-proxy", required_argument, 0, 'b'},
- {"verbose", no_argument, 0, 'v'},
- {"only-proxy", no_argument, 0, 'o'},
- {"statistics", no_argument, 0, 's'},
- {0, 0, 0, 0}
- };
-
- while (1)
- {
- getopt_ret = getopt_long( argc, argv, "p:b:vos", long_options,
&option_index);
- if (getopt_ret == -1)
- break;
-
- switch(getopt_ret)
- {
- case 'p':
- glob_opt.listen_port = atoi(optarg);
- break;
-
- case 'b':
- glob_opt.spdy2http_str = strdup(optarg);
- if(NULL == glob_opt.spdy2http_str)
- return 1;
- break;
-
- case 'v':
- glob_opt.verbose = true;
- break;
-
- case 'o':
- glob_opt.only_proxy = true;
- break;
-
- case 's':
- glob_opt.statistics = true;
- break;
-
- case 0:
- PRINT_INFO("0 from getopt");
- break;
-
- case '?':
- display_usage();
- return 1;
-
- default:
- DIE("default from getopt");
- }
- }
-
- if(
- 0 == glob_opt.listen_port
- || (glob_opt.only_proxy && NULL == glob_opt.spdy2http_str)
- )
- {
- display_usage();
- return 1;
- }
-
- return run_everything();
-}
Deleted: libmicrohttpd/src/examples/mhd2spdy_http.c
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_http.c 2015-12-01 10:19:37 UTC (rev
36707)
+++ libmicrohttpd/src/examples/mhd2spdy_http.c 2015-12-01 13:06:38 UTC (rev
36708)
@@ -1,422 +0,0 @@
-/*
- Copyright Copyright (C) 2013 Andrey Uzunov
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file mhd2spdy_http.c
- * @brief HTTP part of the proxy. libmicrohttpd is used for the server side.
- * @author Andrey Uzunov
- */
-
-#include "mhd2spdy_structures.h"
-#include "mhd2spdy_http.h"
-#include "mhd2spdy_spdy.h"
-
-
-void *
-http_cb_log(void * cls,
-const char * uri)
-{
- (void)cls;
-
- struct HTTP_URI * http_uri;
-
- PRINT_INFO2("log uri '%s'\n", uri);
-
- //TODO not freed once in a while
- if(NULL == (http_uri = au_malloc(sizeof(struct HTTP_URI ))))
- return NULL;
- http_uri->uri = strdup(uri);
- return http_uri;
-}
-
-
-static int
-http_cb_iterate(void *cls,
- enum MHD_ValueKind kind,
- const char *name,
- const char *value)
-{
- (void)kind;
-
- static char * const forbidden[] = {"Transfer-Encoding",
- "Proxy-Connection",
- "Keep-Alive",
- "Connection"};
- static int forbidden_size = 4;
- int i;
- struct SPDY_Headers *spdy_headers = (struct SPDY_Headers *)cls;
-
- if(0 == strcasecmp(name, "Host"))
- spdy_headers->nv[9] = (char *)value;
- else
- {
- for(i=0; i<forbidden_size; ++i)
- if(0 == strcasecmp(forbidden[i], name))
- return MHD_YES;
- spdy_headers->nv[spdy_headers->cnt++] = (char *)name;
- spdy_headers->nv[spdy_headers->cnt++] = (char *)value;
- }
-
- return MHD_YES;
-}
-
-
-static ssize_t
-http_cb_response (void *cls,
- uint64_t pos,
- char *buffer,
- size_t max)
-{
- (void)pos;
-
- int ret;
- struct Proxy *proxy = (struct Proxy *)cls;
- void *newbody;
- const union MHD_ConnectionInfo *info;
- int val = 1;
-
- PRINT_INFO2("http_cb_response for %s", proxy->url);
-
- if(proxy->spdy_error)
- return MHD_CONTENT_READER_END_WITH_ERROR;
-
- if(0 == proxy->http_body_size && (proxy->done || !proxy->spdy_active))
- {
- PRINT_INFO("sent end of stream");
- return MHD_CONTENT_READER_END_OF_STREAM;
- }
-
- if(!proxy->http_body_size)//nothing to write now
- {
- //flush data
- info = MHD_get_connection_info (proxy->http_connection,
- MHD_CONNECTION_INFO_CONNECTION_FD);
- ret = setsockopt(info->connect_fd, IPPROTO_TCP, TCP_NODELAY, &val,
(socklen_t)sizeof(val));
- if(ret == -1) {
- DIE("setsockopt");
- }
-
- PRINT_INFO("FLUSH data");
- return 0;
- }
-
- if(max >= proxy->http_body_size)
- {
- ret = proxy->http_body_size;
- newbody = NULL;
- }
- else
- {
- ret = max;
- if(NULL == (newbody = au_malloc(proxy->http_body_size - max)))
- {
- PRINT_INFO("no memory");
- return MHD_CONTENT_READER_END_WITH_ERROR;
- }
- memcpy(newbody, proxy->http_body + max, proxy->http_body_size -
max);
- }
- memcpy(buffer, proxy->http_body, ret);
- free(proxy->http_body);
- proxy->http_body = newbody;
- proxy->http_body_size -= ret;
-
- if(proxy->length >= 0)
- {
- proxy->length -= ret;
- }
-
- PRINT_INFO2("response_callback, size: %i",ret);
-
- return ret;
-}
-
-
-static void
-http_cb_response_done(void *cls)
-{
- (void)cls;
- //TODO remove
-}
-
-int
-http_cb_request (void *cls,
- struct MHD_Connection *connection,
- const char *url,
- const char *method,
- const char *version,
- const char *upload_data,
- size_t *upload_data_size,
- void **ptr)
-{
- (void)cls;
- (void)url;
- (void)upload_data;
- (void)upload_data_size;
-
- int ret;
- struct Proxy *proxy;
- struct SPDY_Headers spdy_headers;
- bool with_body = false;
- struct HTTP_URI *http_uri;
- const char *header_value;
-
- if (NULL == ptr || NULL == *ptr)
- return MHD_NO;
-
- http_uri = (struct HTTP_URI *)*ptr;
-
- if(NULL == http_uri->proxy)
- {
- //first call for this request
- if (0 != strcmp (method, MHD_HTTP_METHOD_GET) && 0 != strcmp (method,
MHD_HTTP_METHOD_POST))
- {
- free(http_uri->uri);
- free(http_uri);
- PRINT_INFO2("unexpected method %s", method);
- return MHD_NO;
- }
-
- if(NULL == (proxy = au_malloc(sizeof(struct Proxy))))
- {
- free(http_uri->uri);
- free(http_uri);
- PRINT_INFO("No memory");
- return MHD_NO;
- }
-
- ++glob_opt.responses_pending;
- proxy->id = rand();
- proxy->http_active = true;
- proxy->http_connection = connection;
- http_uri->proxy = proxy;
- return MHD_YES;
- }
-
- proxy = http_uri->proxy;
-
- if(proxy->spdy_error || proxy->http_error)
- return MHD_NO; // handled at different place TODO? leaks?
-
- if(proxy->spdy_active)
- {
- if(0 == strcmp (method, MHD_HTTP_METHOD_POST))
- {
- PRINT_INFO("POST processing");
-
- int rc= spdylay_session_resume_data(proxy->spdy_connection->session,
proxy->stream_id);
- PRINT_INFO2("rc is %i stream is %i", rc, proxy->stream_id);
- proxy->spdy_connection->want_io |= WANT_WRITE;
-
- if(0 == *upload_data_size)
- {
- PRINT_INFO("POST http EOF");
- proxy->receiving_done = true;
- return MHD_YES;
- }
-
- if(!copy_buffer(upload_data, *upload_data_size, &proxy->received_body,
&proxy->received_body_size))
- {
- //TODO handle it better?
- PRINT_INFO("not enough memory (malloc/realloc returned NULL)");
- return MHD_NO;
- }
-
- *upload_data_size = 0;
-
- return MHD_YES;
- }
-
- //already handled
- PRINT_INFO("unnecessary call to http_cb_request");
- return MHD_YES;
- }
-
- //second call for this request
-
- PRINT_INFO2("received request for '%s %s %s'", method, http_uri->uri,
version);
-
- proxy->url = http_uri->uri;
-
- header_value = MHD_lookup_connection_value(connection,
- MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_LENGTH);
-
- with_body = 0 == strcmp (method, MHD_HTTP_METHOD_POST)
- && (NULL == header_value || 0 != strcmp ("0", header_value));
-
- PRINT_INFO2("body will be sent %i", with_body);
-
- ret = parse_uri(&glob_opt.uri_preg, proxy->url, &proxy->uri);
- if(ret != 0)
- DIE("parse_uri failed");
- proxy->http_uri = http_uri;
-
- spdy_headers.num = MHD_get_connection_values (connection,
- MHD_HEADER_KIND,
- NULL,
- NULL);
- if(NULL == (spdy_headers.nv = au_malloc(((spdy_headers.num + 5) * 2 + 1) *
sizeof(char *))))
- DIE("no memory");
- spdy_headers.nv[0] = ":method"; spdy_headers.nv[1] = method;
- spdy_headers.nv[2] = ":path"; spdy_headers.nv[3] =
proxy->uri->path_and_more;
- spdy_headers.nv[4] = ":version"; spdy_headers.nv[5] = (char *)version;
- spdy_headers.nv[6] = ":scheme"; spdy_headers.nv[7] = proxy->uri->scheme;
- spdy_headers.nv[8] = ":host"; spdy_headers.nv[9] = NULL;
- //nv[14] = NULL;
- spdy_headers.cnt = 10;
- MHD_get_connection_values (connection,
- MHD_HEADER_KIND,
- &http_cb_iterate,
- &spdy_headers);
-
- spdy_headers.nv[spdy_headers.cnt] = NULL;
- if(NULL == spdy_headers.nv[9])
- spdy_headers.nv[9] = proxy->uri->host_and_port;
-
- if(0 != spdy_request(spdy_headers.nv, proxy, with_body))
- {
- free(spdy_headers.nv);
- //free_proxy(proxy);
-
- return MHD_NO;
- }
- free(spdy_headers.nv);
-
- proxy->http_response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
- 4096,
- &http_cb_response,
- proxy,
- &http_cb_response_done);
-
- if (NULL == proxy->http_response)
- DIE("no response");
-
- if(MHD_NO == MHD_add_response_header (proxy->http_response,
- "Proxy-Connection", "keep-alive"))
- PRINT_INFO("SPDY_name_value_add failed: ");
- if(MHD_NO == MHD_add_response_header (proxy->http_response,
- "Connection", "Keep-Alive"))
- PRINT_INFO("SPDY_name_value_add failed: ");
- if(MHD_NO == MHD_add_response_header (proxy->http_response,
- "Keep-Alive", "timeout=5, max=100"))
- PRINT_INFO("SPDY_name_value_add failed: ");
-
- proxy->spdy_active = true;
-
- return MHD_YES;
-}
-
-
-void
-http_create_response(struct Proxy* proxy,
- char **nv)
-{
- size_t i;
-
- if(!proxy->http_active)
- return;
-
- for(i = 0; nv[i]; i += 2) {
- if(0 == strcmp(":status", nv[i]))
- {
- char tmp[4];
- memcpy(&tmp,nv[i+1],3);
- tmp[3]=0;
- proxy->status = atoi(tmp);
- continue;
- }
- else if(0 == strcmp(":version", nv[i]))
- {
- proxy->version = nv[i+1];
- continue;
- }
- else if(0 == strcmp("content-length", nv[i]))
- {
- continue;
- }
-
- char *header = *(nv+i);
- if(MHD_NO == MHD_add_response_header (proxy->http_response,
- header, nv[i+1]))
- {
- PRINT_INFO2("SPDY_name_value_add failed: '%s' '%s'", header, nv[i+1]);
- }
- PRINT_INFO2("adding '%s: %s'",header, nv[i+1]);
- }
-
- if(MHD_NO == MHD_queue_response (proxy->http_connection, proxy->status,
proxy->http_response)){
- PRINT_INFO("No queue");
- //TODO
- //abort();
- proxy->http_error = true;
- }
-
- MHD_destroy_response (proxy->http_response);
- proxy->http_response = NULL;
-}
-
-void
-http_cb_request_completed (void *cls,
- struct MHD_Connection *connection,
- void **con_cls,
- enum MHD_RequestTerminationCode toe)
-{
- (void)cls;
- (void)connection;
- struct HTTP_URI *http_uri;
- struct Proxy *proxy;
-
- http_uri = (struct HTTP_URI *)*con_cls;
- if(NULL == http_uri)
- return;
- proxy = (struct Proxy *)http_uri->proxy;
- assert(NULL != proxy);
-
- PRINT_INFO2("http_cb_request_completed %i for %s; id %i",toe, http_uri->uri,
proxy->id);
-
- if(NULL != proxy->http_response)
- {
- MHD_destroy_response (proxy->http_response);
- proxy->http_response = NULL;
- }
-
- if(proxy->spdy_active)
- {
- proxy->http_active = false;
- if(MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
- {
- proxy->http_error = true;
- if(proxy->stream_id > 0 /*&& NULL != proxy->spdy_connection->session*/)
- {
- //send RST_STREAM_STATUS_CANCEL
- PRINT_INFO2("send rst_stream %i %i",proxy->spdy_active,
proxy->stream_id );
- spdylay_submit_rst_stream(proxy->spdy_connection->session,
proxy->stream_id, 5);
- }
- /*else
- {
- DLL_remove(proxy->spdy_connection->proxies_head,
proxy->spdy_connection->proxies_tail, proxy);
- free_proxy(proxy);
- }*/
- }
- }
- else
- {
- PRINT_INFO2("proxy free http id %i ", proxy->id);
- free_proxy(proxy);
- }
-
- --glob_opt.responses_pending;
-}
Deleted: libmicrohttpd/src/examples/mhd2spdy_http.h
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_http.h 2015-12-01 10:19:37 UTC (rev
36707)
+++ libmicrohttpd/src/examples/mhd2spdy_http.h 2015-12-01 13:06:38 UTC (rev
36708)
@@ -1,54 +0,0 @@
-/*
- Copyright Copyright (C) 2013 Andrey Uzunov
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file mhd2spdy_http.h
- * @brief HTTP part of the proxy. libmicrohttpd is used for the server side.
- * @author Andrey Uzunov
- */
-
-#ifndef HTTP_H
-#define HTTP_H
-
-#include "mhd2spdy_structures.h"
-
-
-int
-http_cb_request (void *cls,
- struct MHD_Connection *connection,
- const char *url,
- const char *method,
- const char *version,
- const char *upload_data,
- size_t *upload_data_size,
- void **ptr);
-
-
-void * http_cb_log(void * cls, const char * uri);
-
-
-void
-http_create_response(struct Proxy* proxy, char **nv);
-
-
-void
-http_cb_request_completed (void *cls,
- struct MHD_Connection *connection,
- void **con_cls,
- enum MHD_RequestTerminationCode toe);
-
-#endif
Deleted: libmicrohttpd/src/examples/mhd2spdy_spdy.c
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_spdy.c 2015-12-01 10:19:37 UTC (rev
36707)
+++ libmicrohttpd/src/examples/mhd2spdy_spdy.c 2015-12-01 13:06:38 UTC (rev
36708)
@@ -1,1150 +0,0 @@
-/*
- *
- * 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.
- */
-
-/**
- * @file mhd2spdy_spdy.c
- * @brief SPDY part of the proxy. libspdylay is used for the client side.
- * The example spdycli.c from spdylay was used as basis;
- * however, multiple changes were made.
- * @author Tatsuhiro Tsujikawa
- * @author Andrey Uzunov
- */
-
-#include "mhd2spdy_structures.h"
-#include "mhd2spdy_spdy.h"
-#include "mhd2spdy_http.h"
-
-
-/*
- * Prints error containing the function name |func| and message |msg|
- * and exit.
- */
-static void
-spdy_dief(const char *func,
- const char *msg)
-{
- fprintf(stderr, "FATAL: %s: %s\n", func, msg);
- exit(EXIT_FAILURE);
-}
-
-
-/*
- * Prints error containing the function name |func| and error code
- * |error_code| and exit.
- */
-void
-spdy_diec(const char *func,
- int error_code)
-{
- fprintf(stderr, "FATAL: %s: error_code=%d, msg=%s\n", func, error_code,
- spdylay_strerror(error_code));
- exit(EXIT_FAILURE);
-}
-
-
-static ssize_t
-spdy_cb_data_source_read(spdylay_session *session, int32_t stream_id, uint8_t
*buf, size_t length, int *eof, spdylay_data_source *source, void *user_data)
-{
- (void)session;
- (void)stream_id;
- (void)user_data;
-
- ssize_t ret;
- assert(NULL != source);
- assert(NULL != source->ptr);
- struct Proxy *proxy = (struct Proxy *)(source->ptr);
- void *newbody;
-
-
- if(length < 1)
- {
- PRINT_INFO("spdy_cb_data_source_read: length is 0");
- return 0;
- }
-
- if(!proxy->received_body_size)//nothing to write now
- {
- if(proxy->receiving_done)
- {
- PRINT_INFO("POST spdy EOF");
- *eof = 1;
- }
- PRINT_INFO("POST SPDYLAY_ERR_DEFERRED");
- return SPDYLAY_ERR_DEFERRED;//TODO SPDYLAY_ERR_DEFERRED should
be used
- }
-
- if(length >= proxy->received_body_size)
- {
- ret = proxy->received_body_size;
- newbody = NULL;
- }
- else
- {
- ret = length;
- if(NULL == (newbody = malloc(proxy->received_body_size -
length)))
- {
- PRINT_INFO("no memory");
- return SPDYLAY_ERR_TEMPORAL_CALLBACK_FAILURE;
- }
- memcpy(newbody, proxy->received_body + length,
proxy->received_body_size - length);
- }
- memcpy(buf, proxy->received_body, ret);
- free(proxy->received_body);
- proxy->received_body = newbody;
- proxy->received_body_size -= ret;
-
- if(0 == proxy->received_body_size && proxy->receiving_done)
- {
- PRINT_INFO("POST spdy EOF");
- *eof = 1;
- }
-
- PRINT_INFO2("given POST bytes to spdylay: %zd", ret);
-
- return ret;
-}
-
-
-/*
- * The implementation of spdylay_send_callback type. Here we write
- * |data| with size |length| to the network and return the number of
- * bytes actually written. See the documentation of
- * spdylay_send_callback for the details.
- */
-static ssize_t
-spdy_cb_send(spdylay_session *session,
- const uint8_t *data,
- size_t length,
- int flags,
- void *user_data)
-{
- (void)session;
- (void)flags;
-
- //PRINT_INFO("spdy_cb_send called");
- struct SPDY_Connection *connection;
- ssize_t rv;
- connection = (struct SPDY_Connection*)user_data;
- connection->want_io = IO_NONE;
-
- if(glob_opt.ignore_rst_stream
- && 16 == length
- && 0x80 == data[0]
- && 0x00 == data[2]
- && 0x03 == data[3]
- )
- {
- PRINT_INFO2("ignoring RST_STREAM for stream_id %i %i %i %i", data[8],
data[9], data[10], data[11]);
- glob_opt.ignore_rst_stream = false;
- return 16;
- }
- glob_opt.ignore_rst_stream = false;
-
- if(connection->is_tls)
- {
- ERR_clear_error();
- rv = SSL_write(connection->ssl, data, length);
- if(rv < 0) {
- int err = SSL_get_error(connection->ssl, rv);
- if(err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
- connection->want_io |= (err == SSL_ERROR_WANT_READ ?
- WANT_READ : WANT_WRITE);
- rv = SPDYLAY_ERR_WOULDBLOCK;
- } else {
- rv = SPDYLAY_ERR_CALLBACK_FAILURE;
- }
- }
- }
- else
- {
- rv = write(connection->fd,
- data,
- length);
-
- if (rv < 0)
- {
- switch(errno)
- {
- case EAGAIN:
- #if EAGAIN != EWOULDBLOCK
- case EWOULDBLOCK:
- #endif
- connection->want_io |= WANT_WRITE;
- rv = SPDYLAY_ERR_WOULDBLOCK;
- break;
-
- default:
- rv = SPDYLAY_ERR_CALLBACK_FAILURE;
- }
- }
- }
-
- PRINT_INFO2("%zd bytes written by spdy", rv);
-
- if(rv > 0)
- UPDATE_STAT(glob_stat.spdy_bytes_sent, rv);
-
- return rv;
-}
-
-
-/*
- * The implementation of spdylay_recv_callback type. Here we read data
- * from the network and write them in |buf|. The capacity of |buf| is
- * |length| bytes. Returns the number of bytes stored in |buf|. See
- * the documentation of spdylay_recv_callback for the details.
- */
-static ssize_t
-spdy_cb_recv(spdylay_session *session,
- uint8_t *buf,
- size_t length,
- int flags,
- void *user_data)
-{
- (void)session;
- (void)flags;
-
- struct SPDY_Connection *connection;
- ssize_t rv;
-
- connection = (struct SPDY_Connection*)user_data;
- //prevent monopolizing everything
- if(!(++connection->counter % 10)) return SPDYLAY_ERR_WOULDBLOCK;
- connection->want_io = IO_NONE;
- if(connection->is_tls)
- {
- ERR_clear_error();
- rv = SSL_read(connection->ssl, buf, length);
- if(rv < 0) {
- int err = SSL_get_error(connection->ssl, rv);
- if(err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
- connection->want_io |= (err == SSL_ERROR_WANT_READ ?
- WANT_READ : WANT_WRITE);
- rv = SPDYLAY_ERR_WOULDBLOCK;
- } else {
- rv = SPDYLAY_ERR_CALLBACK_FAILURE;
- }
- } else if(rv == 0) {
- rv = SPDYLAY_ERR_EOF;
- }
- }
- else
- {
- rv = read(connection->fd,
- buf,
- length);
-
- if (rv < 0)
- {
- switch(errno)
- {
- case EAGAIN:
- #if EAGAIN != EWOULDBLOCK
- case EWOULDBLOCK:
- #endif
- connection->want_io |= WANT_READ;
- rv = SPDYLAY_ERR_WOULDBLOCK;
- break;
-
- default:
- rv = SPDYLAY_ERR_CALLBACK_FAILURE;
- }
- }
- else if(rv == 0)
- rv = SPDYLAY_ERR_EOF;
- }
-
- if(rv > 0)
- UPDATE_STAT(glob_stat.spdy_bytes_received, rv);
-
- return rv;
-}
-
-
-static void
-spdy_cb_before_ctrl_send(spdylay_session *session,
- spdylay_frame_type type,
- spdylay_frame *frame,
- void *user_data)
-{
- (void)user_data;
-
- int32_t stream_id;
- struct Proxy *proxy;
-
- switch(type) {
- case SPDYLAY_SYN_STREAM:
- stream_id = frame->syn_stream.stream_id;
- proxy = spdylay_session_get_stream_user_data(session, stream_id);
- proxy->stream_id = stream_id;
- ++glob_opt.streams_opened;
- ++proxy->spdy_connection->streams_opened;
- PRINT_INFO2("opening stream: str open %i; %s", glob_opt.streams_opened,
proxy->url);
- break;
- case SPDYLAY_RST_STREAM:
- //try to ignore duplicate RST_STREAMs
- //TODO this will ignore RST_STREAMs also for bogus data
- glob_opt.ignore_rst_stream =
NULL==spdylay_session_get_stream_user_data(session,
frame->rst_stream.stream_id);
- PRINT_INFO2("sending RST_STREAM for %i; ignore %i; status %i",
- frame->rst_stream.stream_id,
- glob_opt.ignore_rst_stream,
- frame->rst_stream.status_code);
- break;
- default:
- break;
- }
-}
-
-
-void
-spdy_cb_on_ctrl_recv(spdylay_session *session,
- spdylay_frame_type type,
- spdylay_frame *frame,
- void *user_data)
-{
- (void)user_data;
-
- char **nv;
- int32_t stream_id;
- struct Proxy * proxy;
-
- switch(type) {
- case SPDYLAY_SYN_REPLY:
- nv = frame->syn_reply.nv;
- stream_id = frame->syn_reply.stream_id;
- break;
- case SPDYLAY_RST_STREAM:
- stream_id = frame->rst_stream.stream_id;
- break;
- case SPDYLAY_HEADERS:
- nv = frame->headers.nv;
- stream_id = frame->headers.stream_id;
- break;
- default:
- return;
- break;
- }
-
- proxy = spdylay_session_get_stream_user_data(session, stream_id);
- if(NULL == proxy)
- {
- PRINT_INFO2("received frame type %i for unkonwn stream id %i", type,
stream_id);
- return;
- //DIE("no proxy obj");
- }
-
- switch(type) {
- case SPDYLAY_SYN_REPLY:
- PRINT_INFO2("received headers for %s", proxy->url);
- http_create_response(proxy, nv);
- break;
- case SPDYLAY_RST_STREAM:
- PRINT_INFO2("received reset stream for %s", proxy->url);
- proxy->spdy_error = true;
- break;
- case SPDYLAY_HEADERS:
- PRINT_INFO2("received headers for %s", proxy->url);
- http_create_response(proxy, nv);
- break;
- default:
- return;
- break;
- }
-
- glob_opt.spdy_data_received = true;
-}
-
-
-/*
- * The implementation of spdylay_on_stream_close_callback type. We use
- * this function to know the response is fully received. Since we just
- * fetch 1 resource in this program, after reception of the response,
- * we submit GOAWAY and close the session.
- */
-static void
-spdy_cb_on_stream_close(spdylay_session *session,
- int32_t stream_id,
- spdylay_status_code status_code,
- void *user_data)
-{
- (void)status_code;
- (void)user_data;
-
- struct Proxy * proxy = spdylay_session_get_stream_user_data(session,
stream_id);
-
- assert(NULL != proxy);
-
- --glob_opt.streams_opened;
- --proxy->spdy_connection->streams_opened;
- PRINT_INFO2("closing stream: str opened %i; remove proxy %i",
glob_opt.streams_opened, proxy->id);
-
- DLL_remove(proxy->spdy_connection->proxies_head,
proxy->spdy_connection->proxies_tail, proxy);
- if(proxy->http_active)
- {
- proxy->spdy_active = false;
- }
- else
- {
- free_proxy(proxy);
- }
-}
-
-
-/*
- * The implementation of spdylay_on_data_chunk_recv_callback type. We
- * use this function to print the received response body.
- */
-static void
-spdy_cb_on_data_chunk_recv(spdylay_session *session,
- uint8_t flags,
- int32_t stream_id,
- const uint8_t *data,
- size_t len,
- void *user_data)
-{
- (void)flags;
- (void)user_data;
-
- struct Proxy *proxy;
- proxy = spdylay_session_get_stream_user_data(session, stream_id);
-
- if(NULL == proxy)
- {
- PRINT_INFO("proxy in spdy_cb_on_data_chunk_recv is NULL)");
- return;
- }
-
- if(!copy_buffer(data, len, &proxy->http_body, &proxy->http_body_size))
- {
- //TODO handle it better?
- PRINT_INFO("not enough memory (malloc/realloc returned NULL)");
- return;
- }
- /*
- if(NULL == proxy->http_body)
- proxy->http_body = au_malloc(len);
- else
- proxy->http_body = realloc(proxy->http_body,
proxy->http_body_size + len);
- if(NULL == proxy->http_body)
- {
- PRINT_INFO("not enough memory (realloc returned NULL)");
- return ;
- }
-
- memcpy(proxy->http_body + proxy->http_body_size, data, len);
- proxy->http_body_size += len;
- */
- PRINT_INFO2("received data for %s; %zu bytes", proxy->url, len);
- glob_opt.spdy_data_received = true;
-}
-
-
-static void
-spdy_cb_on_data_recv(spdylay_session *session,
- uint8_t flags,
- int32_t stream_id,
- int32_t length,
- void *user_data)
-{
- (void)length;
- (void)user_data;
-
- if(flags & SPDYLAY_DATA_FLAG_FIN)
- {
- struct Proxy *proxy;
- proxy = spdylay_session_get_stream_user_data(session, stream_id);
- proxy->done = true;
- PRINT_INFO2("last data frame received for %s", proxy->url);
- }
-}
-
-
-/*
- * Setup callback functions. Spdylay API offers many callback
- * functions, but most of them are optional. The send_callback is
- * always required. Since we use spdylay_session_recv(), the
- * recv_callback is also required.
- */
-static void
-spdy_setup_spdylay_callbacks(spdylay_session_callbacks *callbacks)
-{
- memset(callbacks, 0, sizeof(spdylay_session_callbacks));
- callbacks->send_callback = spdy_cb_send;
- callbacks->recv_callback = spdy_cb_recv;
- callbacks->before_ctrl_send_callback = spdy_cb_before_ctrl_send;
- callbacks->on_ctrl_recv_callback = spdy_cb_on_ctrl_recv;
- callbacks->on_stream_close_callback = spdy_cb_on_stream_close;
- callbacks->on_data_chunk_recv_callback = spdy_cb_on_data_chunk_recv;
- callbacks->on_data_recv_callback = spdy_cb_on_data_recv;
-}
-
-
-/*
- * Callback function for SSL/TLS NPN. Since this program only supports
- * SPDY protocol, if server does not offer SPDY protocol the Spdylay
- * library supports, we terminate program.
- */
-static int
-spdy_cb_ssl_select_next_proto(SSL* ssl,
- unsigned char **out,
- unsigned char *outlen,
- const unsigned char *in,
- unsigned int inlen,
- void *arg)
-{
- (void)ssl;
-
- int rv;
- uint16_t *spdy_proto_version;
-
- /* spdylay_select_next_protocol() selects SPDY protocol version the
- Spdylay library supports. */
- rv = spdylay_select_next_protocol(out, outlen, in, inlen);
- if(rv <= 0) {
- PRINT_INFO("Server did not advertise spdy/2 or spdy/3 protocol.");
- return rv;
- }
- spdy_proto_version = (uint16_t*)arg;
- *spdy_proto_version = rv;
- return SSL_TLSEXT_ERR_OK;
-}
-
-
-/*
- * Setup SSL context. We pass |spdy_proto_version| to get negotiated
- * SPDY protocol version in NPN callback.
- */
-void
-spdy_ssl_init_ssl_ctx(SSL_CTX *ssl_ctx,
- uint16_t *spdy_proto_version)
-{
- /* Disable SSLv2 and enable all workarounds for buggy servers */
- SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2 |
SSL_OP_NO_COMPRESSION);
- SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
- SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
- /* Set NPN callback */
- SSL_CTX_set_next_proto_select_cb(ssl_ctx, spdy_cb_ssl_select_next_proto,
- spdy_proto_version);
-}
-
-
-static int
-spdy_ssl_handshake(SSL *ssl,
- int fd)
-{
- int rv;
-
- if(SSL_set_fd(ssl, fd) == 0)
- spdy_dief("SSL_set_fd", ERR_error_string(ERR_get_error(), NULL));
-
- ERR_clear_error();
- rv = SSL_connect(ssl);
- if(rv <= 0)
- PRINT_INFO2("SSL_connect %s", ERR_error_string(ERR_get_error(), NULL));
-
- return rv;
-}
-
-
-/*
- * Connects to the host |host| and port |port|. This function returns
- * the file descriptor of the client socket.
- */
-static int
-spdy_socket_connect_to(const char *host,
- uint16_t port)
-{
- struct addrinfo hints;
- int fd = -1;
- int rv;
- char service[NI_MAXSERV];
- struct addrinfo *res, *rp;
-
- //TODO checks
- snprintf(service, sizeof(service), "%u", port);
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- rv = getaddrinfo(host, service, &hints, &res);
- if(rv != 0)
- {
- printf("%s\n",host);
- spdy_dief("getaddrinfo", gai_strerror(rv));
- }
- for(rp = res; rp; rp = rp->ai_next)
- {
- fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
- if(fd == -1)
- continue;
- while((rv = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 &&
- errno == EINTR);
- if(rv == 0)
- break;
- MHD_socket_close_ (fd);
- fd = -1;
- }
- freeaddrinfo(res);
-
- return fd;
-}
-
-
-static void
-spdy_socket_make_non_block(int fd)
-{
- int flags;
- int rv;
-
- while((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR);
-
- if(flags == -1)
- spdy_dief("fcntl", strerror(errno));
-
- while((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR);
-
- if(rv == -1)
- spdy_dief("fcntl", strerror(errno));
-}
-
-
-/*
- * Setting TCP_NODELAY is not mandatory for the SPDY protocol.
- */
-static void
-spdy_socket_set_tcp_nodelay(int fd)
-{
- int val = 1;
- int rv;
-
- rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val));
- if(rv == -1)
- spdy_dief("setsockopt", strerror(errno));
-}
-
-/*
- * Update |pollfd| based on the state of |connection|.
- */
- /*
-void
-spdy_ctl_poll(struct pollfd *pollfd,
- struct SPDY_Connection *connection)
-{
- pollfd->events = 0;
- if(spdylay_session_want_read(connection->session) ||
- connection->want_io & WANT_READ)
- {
- pollfd->events |= POLLIN;
- }
- if(spdylay_session_want_write(connection->session) ||
- connection->want_io & WANT_WRITE)
- {
- pollfd->events |= POLLOUT;
- }
-}*/
-
-
-/*
- * Update |selectfd| based on the state of |connection|.
- */
-bool
-spdy_ctl_select(fd_set * read_fd_set,
- fd_set * write_fd_set,
- fd_set * except_fd_set,
- struct SPDY_Connection *connection)
-{
- (void)except_fd_set;
-
- bool ret = false;
-
- if(spdylay_session_want_read(connection->session) ||
- connection->want_io & WANT_READ)
- {
- FD_SET(connection->fd, read_fd_set);
- ret = true;
- }
- if(spdylay_session_want_write(connection->session) ||
- connection->want_io & WANT_WRITE)
- {
- FD_SET(connection->fd, write_fd_set);
- ret = true;
- }
-
- return ret;
-}
-
-
-/*
- * Performs the network I/O.
- */
-int
-spdy_exec_io(struct SPDY_Connection *connection)
-{
- int rv;
-
- rv = spdylay_session_recv(connection->session);
- if(rv != 0)
- {
- PRINT_INFO2("spdylay_session_recv %i", rv);
- return rv;
- }
- rv = spdylay_session_send(connection->session);
- if(rv != 0)
- PRINT_INFO2("spdylay_session_send %i", rv);
-
- return rv;
-}
-
-
-/*
- * Fetches the resource denoted by |uri|.
- */
-struct SPDY_Connection *
-spdy_connect(const struct URI *uri,
- uint16_t port,
- bool is_tls)
-{
- spdylay_session_callbacks callbacks;
- int fd;
- SSL *ssl=NULL;
- struct SPDY_Connection * connection = NULL;
- int rv;
-
- spdy_setup_spdylay_callbacks(&callbacks);
-
- /* Establish connection and setup SSL */
- PRINT_INFO2("connecting to %s:%i", uri->host, port);
- fd = spdy_socket_connect_to(uri->host, port);
- if(fd == -1)
- {
- PRINT_INFO("Could not open file descriptor");
- return NULL;
- }
-
- if(is_tls)
- {
- ssl = SSL_new(glob_opt.ssl_ctx);
- if(ssl == NULL) {
- spdy_dief("SSL_new", ERR_error_string(ERR_get_error(), NULL));
- }
-
- //TODO non-blocking
- /* To simplify the program, we perform SSL/TLS handshake in blocking
- I/O. */
- glob_opt.spdy_proto_version = 0;
- rv = spdy_ssl_handshake(ssl, fd);
- if(rv <= 0 || (glob_opt.spdy_proto_version != 3 &&
glob_opt.spdy_proto_version != 2))
- {
- PRINT_INFO("Closing SSL");
- //no spdy on the other side
- goto free_and_fail;
- }
- }
- else
- {
- glob_opt.spdy_proto_version = 3;
- }
-
- if(NULL == (connection = au_malloc(sizeof(struct SPDY_Connection))))
- goto free_and_fail;
-
- connection->is_tls = is_tls;
- connection->ssl = ssl;
- connection->want_io = IO_NONE;
- if(NULL == (connection->host = strdup(uri->host)))
- goto free_and_fail;
-
- /* Here make file descriptor non-block */
- spdy_socket_make_non_block(fd);
- spdy_socket_set_tcp_nodelay(fd);
-
- PRINT_INFO2("[INFO] SPDY protocol version = %d\n",
glob_opt.spdy_proto_version);
- rv = spdylay_session_client_new(&(connection->session),
glob_opt.spdy_proto_version,
- &callbacks, connection);
- if(rv != 0) {
- spdy_diec("spdylay_session_client_new", rv);
- }
-
- connection->fd = fd;
-
- return connection;
-
- //for GOTO
- free_and_fail:
- if(NULL != connection)
- {
- free(connection->host);
- free(connection);
- }
-
- if(is_tls)
- SSL_shutdown(ssl);
-
- MHD_socket_close_ (fd);
-
- if(is_tls)
- SSL_free(ssl);
-
- return NULL;
-}
-
-
-void
-spdy_free_connection(struct SPDY_Connection * connection)
-{
- struct Proxy *proxy;
- struct Proxy *proxy_next;
-
- if(NULL != connection)
- {
- for(proxy = connection->proxies_head; NULL != proxy; proxy=proxy_next)
- {
- proxy_next = proxy->next;
- DLL_remove(connection->proxies_head, connection->proxies_tail, proxy);
- proxy->spdy_active = false;
- proxy->spdy_error = true;
- PRINT_INFO2("spdy_free_connection for id %i", proxy->id);
- if(!proxy->http_active)
- {
- free_proxy(proxy);
- }
- }
- spdylay_session_del(connection->session);
- SSL_free(connection->ssl);
- free(connection->host);
- free(connection);
- //connection->session = NULL;
- }
-}
-
-
-int
-spdy_request(const char **nv,
- struct Proxy *proxy,
- bool with_body)
-{
- int ret;
- uint16_t port;
- struct SPDY_Connection *connection;
- spdylay_data_provider post_data;
-
- if(glob_opt.only_proxy)
- {
- connection = glob_opt.spdy_connection;
- }
- else
- {
- connection = glob_opt.spdy_connections_head;
- while(NULL != connection)
- {
- if(0 == strcasecmp(proxy->uri->host, connection->host))
- break;
- connection = connection->next;
- }
-
- if(NULL == connection)
- {
- //connect to host
- port = proxy->uri->port;
- if(0 == port) port = 443;
- connection = spdy_connect(proxy->uri, port, true);
- if(NULL != connection)
- {
- DLL_insert(glob_opt.spdy_connections_head,
glob_opt.spdy_connections_tail, connection);
- glob_opt.total_spdy_connections++;
- }
- else
- connection = glob_opt.spdy_connection;
- }
- }
-
- if(NULL == connection)
- {
- PRINT_INFO("there is no proxy!");
- return -1;
- }
-
- proxy->spdy_connection = connection;
- if(with_body)
- {
- post_data.source.ptr = proxy;
- post_data.read_callback = &spdy_cb_data_source_read;
- ret = spdylay_submit_request(connection->session, 0, nv, &post_data,
proxy);
- }
- else
- ret = spdylay_submit_request(connection->session, 0, nv, NULL, proxy);
-
- if(ret != 0) {
- spdy_diec("spdylay_spdy_submit_request", ret);
- }
- PRINT_INFO2("adding proxy %i", proxy->id);
- if(NULL != connection->proxies_head)
- PRINT_INFO2("before proxy %i", connection->proxies_head->id);
- DLL_insert(connection->proxies_head, connection->proxies_tail, proxy);
-
- return ret;
-}
-
-/*
-void
-spdy_get_pollfdset(struct pollfd fds[],
- struct SPDY_Connection *connections[],
- unsigned int max_size,
- nfds_t *real_size)
-{
- struct SPDY_Connection *connection;
- struct Proxy *proxy;
-
- *real_size = 0;
- if(max_size<1)
- return;
-
- if(NULL != glob_opt.spdy_connection)
- {
- spdy_ctl_poll(&(fds[*real_size]), glob_opt.spdy_connection);
- if(!fds[*real_size].events)
- {
- //PRINT_INFO("TODO drop connection");
- glob_opt.streams_opened -= glob_opt.spdy_connection->streams_opened;
-
- for(proxy = glob_opt.spdy_connection->proxies_head; NULL != proxy;
proxy=proxy->next)
- {
- abort();
- DLL_remove(glob_opt.spdy_connection->proxies_head,
glob_opt.spdy_connection->proxies_tail, proxy);
- proxy->spdy_active = false;
- }
- spdy_free_connection(glob_opt.spdy_connection);
- glob_opt.spdy_connection = NULL;
- }
- else
- {
- fds[*real_size].fd = glob_opt.spdy_connection->fd;
- connections[*real_size] = glob_opt.spdy_connection;
- ++(*real_size);
- }
- }
-
- connection = glob_opt.spdy_connections_head;
-
- while(NULL != connection && *real_size < max_size)
- {
- assert(!glob_opt.only_proxy);
- spdy_ctl_poll(&(fds[*real_size]), connection);
- if(!fds[*real_size].events)
- {
- //PRINT_INFO("TODO drop connection");
- glob_opt.streams_opened -= connection->streams_opened;
- DLL_remove(glob_opt.spdy_connections_head,
glob_opt.spdy_connections_tail, connection);
- glob_opt.total_spdy_connections--;
-
- for(proxy = connection->proxies_head; NULL != proxy; proxy=proxy->next)
- {
- abort();
- DLL_remove(connection->proxies_head, connection->proxies_tail, proxy);
- proxy->spdy_active = false;
- }
- spdy_free_connection(connection);
- }
- else
- {
- fds[*real_size].fd = connection->fd;
- connections[*real_size] = connection;
- ++(*real_size);
- }
- connection = connection->next;
- }
-
- //, "TODO max num of conn reached; close something"
- assert(NULL == connection);
-}
-*/
-
-int
-spdy_get_selectfdset(fd_set * read_fd_set,
- fd_set * write_fd_set,
- fd_set * except_fd_set,
- struct SPDY_Connection *connections[],
- unsigned int max_size,
- nfds_t *real_size)
-{
- struct SPDY_Connection *connection;
- struct SPDY_Connection *next_connection;
- bool ret;
- int maxfd = 0;
-
- *real_size = 0;
- if(max_size<1)
- return 0;
-
- if(NULL != glob_opt.spdy_connection)
- {
- ret = spdy_ctl_select(read_fd_set,
- write_fd_set,
- except_fd_set, glob_opt.spdy_connection);
- if(!ret)
- {
- glob_opt.streams_opened -= glob_opt.spdy_connection->streams_opened;
-
- PRINT_INFO("spdy_free_connection in spdy_get_selectfdset");
- spdy_free_connection(glob_opt.spdy_connection);
- glob_opt.spdy_connection = NULL;
- }
- else
- {
- connections[*real_size] = glob_opt.spdy_connection;
- ++(*real_size);
- if(maxfd < glob_opt.spdy_connection->fd) maxfd =
glob_opt.spdy_connection->fd;
- }
- }
-
- connection = glob_opt.spdy_connections_head;
-
- while(NULL != connection && *real_size < max_size)
- {
- assert(!glob_opt.only_proxy);
- ret = spdy_ctl_select(read_fd_set,
- write_fd_set,
- except_fd_set, connection);
-
- next_connection = connection->next;
- if(!ret)
- {
- glob_opt.streams_opened -= connection->streams_opened;
- DLL_remove(glob_opt.spdy_connections_head,
glob_opt.spdy_connections_tail, connection);
- glob_opt.total_spdy_connections--;
-
- PRINT_INFO("spdy_free_connection in spdy_get_selectfdset");
- spdy_free_connection(connection);
- }
- else
- {
- connections[*real_size] = connection;
- ++(*real_size);
- if(maxfd < connection->fd) maxfd = connection->fd;
- }
- connection = next_connection;
- }
-
- //, "TODO max num of conn reached; close something"
- assert(NULL == connection);
-
- return maxfd;
-}
-
-/*
-void
-spdy_run(struct pollfd fds[],
- struct SPDY_Connection *connections[],
- int size)
-{
- int i;
- int ret;
- struct Proxy *proxy;
-
- for(i=0; i<size; ++i)
- {
- // PRINT_INFO2("exec about to be called for %s", connections[i]->host);
- if(fds[i].revents & (POLLIN | POLLOUT))
- {
- ret = spdy_exec_io(connections[i]);
- //PRINT_INFO2("%i",ret);
- //if((spdy_pollfds[i].revents & POLLHUP) || (spdy_pollfds[0].revents &
POLLERR))
- // PRINT_INFO("SPDY SPDY_Connection error");
-
- //TODO POLLRDHUP
- // always close on ret != 0?
-
- if(0 != ret)
- {
- glob_opt.streams_opened -= connections[i]->streams_opened;
- if(connections[i] == glob_opt.spdy_connection)
- {
- glob_opt.spdy_connection = NULL;
- }
- else
- {
- DLL_remove(glob_opt.spdy_connections_head,
glob_opt.spdy_connections_tail, connections[i]);
- glob_opt.total_spdy_connections--;
- }
- for(proxy = connections[i]->proxies_head; NULL != proxy;
proxy=proxy->next)
- {
- abort();
- DLL_remove(connections[i]->proxies_head,
connections[i]->proxies_tail, proxy);
- proxy->spdy_active = false;
- proxy->spdy_error = true;
- PRINT_INFO2("spdy_free_connection for id %i", proxy->id);
- }
- PRINT_INFO("spdy_free_connection in loop");
- spdy_free_connection(connections[i]);
- }
- }
- else
- PRINT_INFO("not called");
- }
-}
-*/
-
-void
-spdy_run_select(fd_set * read_fd_set,
- fd_set * write_fd_set,
- fd_set * except_fd_set,
- struct SPDY_Connection *connections[],
- int size)
-{
- int i;
- int ret;
-
- for(i=0; i<size; ++i)
- {
- // PRINT_INFO2("exec about to be called for %s", connections[i]->host);
- if(FD_ISSET(connections[i]->fd, read_fd_set) ||
FD_ISSET(connections[i]->fd, write_fd_set) || FD_ISSET(connections[i]->fd,
except_fd_set))
- {
- //raise(SIGINT);
- ret = spdy_exec_io(connections[i]);
-
- if(0 != ret)
- {
- glob_opt.streams_opened -= connections[i]->streams_opened;
- if(connections[i] == glob_opt.spdy_connection)
- {
- glob_opt.spdy_connection = NULL;
- }
- else
- {
- DLL_remove(glob_opt.spdy_connections_head,
glob_opt.spdy_connections_tail, connections[i]);
- glob_opt.total_spdy_connections--;
- }
- PRINT_INFO("in spdy_run_select");
- spdy_free_connection(connections[i]);
- }
- }
- else
- {
- PRINT_INFO("not called");
- //PRINT_INFO2("connection->want_io %i",connections[i]->want_io);
- //PRINT_INFO2("read
%i",spdylay_session_want_read(connections[i]->session));
- //PRINT_INFO2("write
%i",spdylay_session_want_write(connections[i]->session));
- //raise(SIGINT);
- }
- }
-}
Deleted: libmicrohttpd/src/examples/mhd2spdy_spdy.h
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_spdy.h 2015-12-01 10:19:37 UTC (rev
36707)
+++ libmicrohttpd/src/examples/mhd2spdy_spdy.h 2015-12-01 13:06:38 UTC (rev
36708)
@@ -1,102 +0,0 @@
-/*
- Copyright Copyright (C) 2013 Andrey Uzunov
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file mhd2spdy_spdy.h
- * @brief SPDY part of the proxy. libspdylay is used for the client side.
- * @author Andrey Uzunov
- */
-
-#ifndef SPDY_H
-#define SPDY_H
-
-#include "mhd2spdy_structures.h"
-
-
-struct SPDY_Connection *
-spdy_connect(const struct URI *uri,
- uint16_t port,
- bool is_tls);
-
-
-void
-spdy_ctl_poll(struct pollfd *pollfd,
- struct SPDY_Connection *connection);
-
-
-bool
-spdy_ctl_select(fd_set * read_fd_set,
- fd_set * write_fd_set,
- fd_set * except_fd_set,
- struct SPDY_Connection *connection);
-
-
-int
-spdy_exec_io(struct SPDY_Connection *connection);
-
-
-void
-spdy_diec(const char *func,
- int error_code);
-
-
-int
-spdy_request(const char **nv,
- struct Proxy *proxy,
- bool with_body);
-
-
-void
-spdy_ssl_init_ssl_ctx(SSL_CTX *ssl_ctx,
- uint16_t *spdy_proto_version);
-
-
-void
-spdy_free_connection(struct SPDY_Connection * connection);
-
-
-void
-spdy_get_pollfdset(struct pollfd fds[],
- struct SPDY_Connection *connections[],
- unsigned int max_size,
- nfds_t *real_size);
-
-
-int
-spdy_get_selectfdset(fd_set * read_fd_set,
- fd_set * write_fd_set,
- fd_set * except_fd_set,
- struct SPDY_Connection *connections[],
- unsigned int max_size,
- nfds_t *real_size);
-
-
-void
-spdy_run(struct pollfd fds[],
- struct SPDY_Connection *connections[],
- int size);
-
-
-void
-spdy_run_select(fd_set * read_fd_set,
- fd_set * write_fd_set,
- fd_set * except_fd_set,
- struct SPDY_Connection *connections[],
- int size);
-
-
-#endif
Deleted: libmicrohttpd/src/examples/mhd2spdy_structures.c
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_structures.c 2015-12-01 10:19:37 UTC
(rev 36707)
+++ libmicrohttpd/src/examples/mhd2spdy_structures.c 2015-12-01 13:06:38 UTC
(rev 36708)
@@ -1,162 +0,0 @@
-/*
- Copyright Copyright (C) 2013 Andrey Uzunov
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file mhd2spdy_structures.h
- * @brief Common functions, macros.
- * @author Andrey Uzunov
- */
-
-#include "mhd2spdy_structures.h"
-
-
-void
-free_uri(struct URI * uri)
-{
- if(NULL != uri)
- {
- free(uri->full_uri);
- free(uri->scheme);
- free(uri->host_and_port);
- free(uri->host);
- free(uri->path);
- free(uri->path_and_more);
- free(uri->query);
- free(uri->fragment);
- uri->port = 0;
- free(uri);
- }
-}
-
-
-int
-init_parse_uri(regex_t * preg)
-{
- // RFC 2396
- // ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- /*
- scheme = $2
- authority = $4
- path = $5
- query = $7
- fragment = $9
- */
-
- return regcomp(preg,
"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?", REG_EXTENDED);
-}
-
-void
-deinit_parse_uri(regex_t * preg)
-{
- regfree(preg);
-}
-
-int
-parse_uri(regex_t * preg,
- char * full_uri,
- struct URI ** uri)
-{
- int ret;
- char *colon;
- long long port;
- size_t nmatch = 10;
- regmatch_t pmatch[10];
-
- if (0 != (ret = regexec(preg, full_uri, nmatch, pmatch, 0)))
- return ret;
-
- *uri = au_malloc(sizeof(struct URI));
- if(NULL == *uri)
- return -200;
-
- (*uri)->full_uri = strdup(full_uri);
-
- asprintf(&((*uri)->scheme), "%.*s",pmatch[2].rm_eo - pmatch[2].rm_so,
&full_uri[pmatch[2].rm_so]);
- asprintf(&((*uri)->host_and_port), "%.*s",pmatch[4].rm_eo - pmatch[4].rm_so,
&full_uri[pmatch[4].rm_so]);
- asprintf(&((*uri)->path), "%.*s",pmatch[5].rm_eo - pmatch[5].rm_so,
&full_uri[pmatch[5].rm_so]);
- asprintf(&((*uri)->path_and_more), "%.*s",pmatch[9].rm_eo - pmatch[5].rm_so,
&full_uri[pmatch[5].rm_so]);
- asprintf(&((*uri)->query), "%.*s",pmatch[7].rm_eo - pmatch[7].rm_so,
&full_uri[pmatch[7].rm_so]);
- asprintf(&((*uri)->fragment), "%.*s",pmatch[9].rm_eo - pmatch[9].rm_so,
&full_uri[pmatch[9].rm_so]);
-
- colon = strrchr((*uri)->host_and_port, ':');
- if(NULL == colon)
- {
- (*uri)->host = strdup((*uri)->host_and_port);
- (*uri)->port = 0;
-
- return 0;
- }
-
- port = atoi(colon + 1);
- if(port<1 || port >= 256 * 256)
- {
- free_uri(*uri);
- return -100;
- }
- (*uri)->port = port;
- asprintf(&((*uri)->host), "%.*s", (int)(colon - (*uri)->host_and_port),
(*uri)->host_and_port);
-
- return 0;
-}
-
-
-void
-free_proxy(struct Proxy *proxy)
-{
- PRINT_INFO2("free proxy called for '%s'", proxy->url);
- if(NULL != proxy->http_body && proxy->http_body_size > 0)
- UPDATE_STAT(glob_stat.spdy_bytes_received_and_dropped,
proxy->http_body_size);
- free(proxy->http_body);
- free_uri(proxy->uri);
- free(proxy->url);
- free(proxy->http_uri);
- free(proxy);
-}
-
-
-void *au_malloc(size_t size)
-{
- void *new_memory;
-
- new_memory = malloc(size);
- if(NULL != new_memory)
- {
- glob_opt.global_memory += size;
- memset(new_memory, 0, size);
- }
- return new_memory;
-}
-
-
-bool
-copy_buffer(const void *src, size_t src_size, void **dst, size_t *dst_size)
-{
- if(0 == src_size)
- return true;
-
- if(NULL == *dst)
- *dst = malloc(src_size);
- else
- *dst = realloc(*dst, src_size + *dst_size);
- if(NULL == *dst)
- return false;
-
- memcpy(*dst + *dst_size, src, src_size);
- *dst_size += src_size;
-
- return true;
-}
Deleted: libmicrohttpd/src/examples/mhd2spdy_structures.h
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_structures.h 2015-12-01 10:19:37 UTC
(rev 36707)
+++ libmicrohttpd/src/examples/mhd2spdy_structures.h 2015-12-01 13:06:38 UTC
(rev 36708)
@@ -1,296 +0,0 @@
-/*
- Copyright Copyright (C) 2013 Andrey Uzunov
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file mhd2spdy_structures.h
- * @brief Common structures, functions, macros and global variables.
- * @author Andrey Uzunov
- */
-#ifndef STRUCTURES_H
-#define STRUCTURES_H
-
-#define _GNU_SOURCE
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#include <assert.h>
-#include <microhttpd.h>
-#include <signal.h>
-#include <poll.h>
-#include <fcntl.h>
-#include <regex.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <spdylay/spdylay.h>
-#include <getopt.h>
-
-
-/* WANT_READ if SSL connection needs more input; or WANT_WRITE if it
- needs more output; or IO_NONE. This is necessary because SSL/TLS
- re-negotiation is possible at any time. Spdylay API offers
- similar functions like spdylay_session_want_read() and
- spdylay_session_want_write() but they do not take into account
- SSL connection. */
-enum
-{
- IO_NONE,
- WANT_READ,
- WANT_WRITE
-};
-
-
-struct Proxy;
-
-
-struct SPDY_Connection {
- SSL *ssl;
- spdylay_session *session;
- struct SPDY_Connection *prev;
- struct SPDY_Connection *next;
- struct Proxy *proxies_head;
- struct Proxy *proxies_tail;
- char *host;
- int fd;
- int want_io;
- uint counter;
- uint streams_opened;
- bool is_tls;
-};
-
-
-struct URI
-{
- char * full_uri;
- char * scheme;
- char * host_and_port;
- char * host;
- char * path;
- char * path_and_more;
- char * query;
- char * fragment;
- uint16_t port;
-};
-
-
-struct HTTP_URI;
-
-
-struct Proxy
-{
- struct MHD_Connection *http_connection;
- struct MHD_Response *http_response;
- struct URI *uri;
- struct HTTP_URI *http_uri;
- struct SPDY_Connection *spdy_connection;
- struct Proxy *next;
- struct Proxy *prev;
- char *url;
- char *version;
- void *http_body;
- void *received_body;
- size_t http_body_size;
- size_t received_body_size;
- ssize_t length;
- int status;
- int id;
- int32_t stream_id;
- bool done;
- bool http_error;
- bool spdy_error;
- bool http_active;
- bool spdy_active;
- bool receiving_done;
-};
-
-
-struct HTTP_URI
-{
- char * uri;
- struct Proxy * proxy;
-};
-
-
-struct SPDY_Headers
-{
- const char **nv;
- int num;
- int cnt;
-};
-
-
-struct global_options
-{
- char *spdy2http_str;
- struct SPDY_Connection *spdy_connection;
- struct SPDY_Connection *spdy_connections_head;
- struct SPDY_Connection *spdy_connections_tail;
- int streams_opened;
- int responses_pending;
- regex_t uri_preg;
- size_t global_memory;
- SSL_CTX *ssl_ctx;
- uint32_t total_spdy_connections;
- uint16_t spdy_proto_version;
- uint16_t listen_port;
- bool verbose;
- bool only_proxy;
- bool spdy_data_received;
- bool statistics;
- bool ignore_rst_stream;
-}
-glob_opt;
-
-
-struct global_statistics
-{
- //unsigned long long http_bytes_sent;
- //unsigned long long http_bytes_received;
- unsigned long long spdy_bytes_sent;
- unsigned long long spdy_bytes_received;
- unsigned long long spdy_bytes_received_and_dropped;
-}
-glob_stat;
-
-
-//forbidden headers
-#define SPDY_HTTP_HEADER_TRANSFER_ENCODING "transfer-encoding"
-#define SPDY_HTTP_HEADER_PROXY_CONNECTION "proxy-connection"
-#define SPDY_HTTP_HEADER_KEEP_ALIVE "keep-alive"
-#define SPDY_HTTP_HEADER_CONNECTION "connection"
-
-#define MAX_SPDY_CONNECTIONS 100
-
-#define SPDY_MAX_OUTLEN 4096
-
-/**
- * Insert an element at the head of a DLL. Assumes that head, tail and
- * element are structs with prev and next fields.
- *
- * @param head pointer to the head of the DLL (struct ? *)
- * @param tail pointer to the tail of the DLL (struct ? *)
- * @param element element to insert (struct ? *)
- */
-#define DLL_insert(head,tail,element) do { \
- (element)->next = (head); \
- (element)->prev = NULL; \
- if ((tail) == NULL) \
- (tail) = element; \
- else \
- (head)->prev = element; \
- (head) = (element); } while (0)
-
-
-/**
- * Remove an element from a DLL. Assumes
- * that head, tail and element are structs
- * with prev and next fields.
- *
- * @param head pointer to the head of the DLL (struct ? *)
- * @param tail pointer to the tail of the DLL (struct ? *)
- * @param element element to remove (struct ? *)
- */
-#define DLL_remove(head,tail,element) do { \
- if ((element)->prev == NULL) \
- (head) = (element)->next; \
- else \
- (element)->prev->next = (element)->next; \
- if ((element)->next == NULL) \
- (tail) = (element)->prev; \
- else \
- (element)->next->prev = (element)->prev; \
- (element)->next = NULL; \
- (element)->prev = NULL; } while (0)
-
-
-#define PRINT_INFO(msg) do{\
- if(glob_opt.verbose){\
- printf("%i:%s\n", __LINE__, msg);\
- fflush(stdout);\
- }\
- }\
- while(0)
-
-
-#define PRINT_INFO2(fmt, ...) do{\
- if(glob_opt.verbose){\
- printf("%i\n", __LINE__);\
- printf(fmt,##__VA_ARGS__);\
- printf("\n");\
- fflush(stdout);\
- }\
- }\
- while(0)
-
-
-#define DIE(msg) do{\
- printf("FATAL ERROR (line %i): %s\n", __LINE__, msg);\
- fflush(stdout);\
- exit(EXIT_FAILURE);\
- }\
- while(0)
-
-
-#define UPDATE_STAT(stat, value) do{\
- if(glob_opt.statistics)\
- {\
- stat += value;\
- }\
- }\
- while(0)
-
-
-void
-free_uri(struct URI * uri);
-
-
-int
-init_parse_uri(regex_t * preg);
-
-
-void
-deinit_parse_uri(regex_t * preg);
-
-
-int
-parse_uri(regex_t * preg,
- char * full_uri,
- struct URI ** uri);
-
-
-void
-free_proxy(struct Proxy *proxy);
-
-
-void *
-au_malloc(size_t size);
-
-
-bool
-copy_buffer(const void *src, size_t src_size, void **dst, size_t *dst_size);
-
-#endif
Deleted: libmicrohttpd/src/examples/spdy_event_loop.c
===================================================================
--- libmicrohttpd/src/examples/spdy_event_loop.c 2015-12-01 10:19:37 UTC
(rev 36707)
+++ libmicrohttpd/src/examples/spdy_event_loop.c 2015-12-01 13:06:38 UTC
(rev 36708)
@@ -1,487 +0,0 @@
-/*
- This file is part of libmicrospdy
- Copyright Copyright (C) 2012 Andrey Uzunov
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file event_loop.c
- * @brief shows how to use the daemon. THIS IS MAINLY A TEST AND DEBUG
- * PROGRAM
- * @author Andrey Uzunov
- */
-
-#include "platform.h"
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#include "microspdy.h"
-#include <sys/time.h>
-#include <time.h>
-#ifndef MINGW
-#include <arpa/inet.h>
-#endif
-//#include "../framinglayer/structures.h"
-//#include "../applicationlayer/alstructures.h"
-
-static int run = 1;
-
-static int run2 = 1;
-
-
-static uint64_t loops;
-
-static time_t start;
-
-
-static void
-new_session_callback (void *cls,
- struct SPDY_Session * session)
-{
- (void)cls;
-
- char ipstr[1024];
-
- struct sockaddr *addr;
- socklen_t addr_len = SPDY_get_remote_addr(session, &addr);
-
- if(!addr_len)
- {
- printf("SPDY_get_remote_addr");
- abort();
- }
-
- if(AF_INET == addr->sa_family)
- {
- struct sockaddr_in * addr4 = (struct sockaddr_in *) addr;
- if(NULL == inet_ntop(AF_INET, &(addr4->sin_addr), ipstr,
sizeof(ipstr)))
- {
- printf("inet_ntop");
- abort();
- }
- printf("New connection from: %s:%i\n", ipstr,
ntohs(addr4->sin_port));
-
- }
- else if(AF_INET6 == addr->sa_family)
- {
- struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *) addr;
- if(NULL == inet_ntop(AF_INET6, &(addr6->sin6_addr), ipstr,
sizeof(ipstr)))
- {
- printf("inet_ntop");
- abort();
- }
- printf("New connection from: %s:%i\n", ipstr,
ntohs(addr6->sin6_port));
-
- }
-}
-
-
-static void
-session_closed_handler (void *cls,
- struct SPDY_Session * session,
- int by_client)
-{
- (void)cls;
- (void)session;
-
- //printf("session_closed_handler called\n");
-
- if(SPDY_YES != by_client)
- {
- //killchild(child,"wrong by_client");
- printf("session closed by server\n");
- }
- else
- {
- printf("session closed by client\n");
- }
-
- //session_closed_called = 1;
-}
-
-
-static void
-response_done_callback(void *cls,
- struct SPDY_Response *response,
- struct SPDY_Request *request,
- enum SPDY_RESPONSE_RESULT
status,
- bool streamopened)
-{
- (void)streamopened;
- if(strcmp(cls, "/close (daemon1)") == 0)
- run = 0;
- else {
- if(strcmp(cls, "/close (daemon2)") == 0) run2 = 0;
- loops = 0;
- start = time(NULL);
- }
- if(SPDY_RESPONSE_RESULT_SUCCESS != status)
- {
- printf("not sent frame cause %i", status);
- }
- printf("answer for %s was sent\n", (char*)cls);
- //printf("raw sent headers %s\n", (char *)(response->headers)+8);
-
- SPDY_destroy_request(request);
- SPDY_destroy_response(response);
- free(cls);
-}
-
-/*
-static int
-print_headers (void *cls,
- const char *name, const char *value)
-{
- (void)cls;
- printf("%s: %s\n",name,value);
- return SPDY_YES;
-}
- */
-
-
-/*
-void
-new_request_cb (void *cls,
- struct SPDY_Request * request,
- uint8_t priority,
- const char *method,
- const char *path,
- const char *version,
- const char *host,
- const char *scheme,
- struct SPDY_NameValue * headers)
-{
- (void)cls;
- (void)request;
- printf("Priority: %i\nHTTP headers, scheme: %s\n\n%s %s %s\nHost:
%s\n", priority,scheme,method,path,version,host);
- SPDY_name_value_iterate(headers, &print_headers, NULL);
-}
-*/
-
-
-static int
-append_headers_to_data (void *cls,
- const char *name, const char * const *value, int
num_values)
-{
- char **data = cls;
- void *tofree = *data;
- int i;
-
- if(num_values)
- for(i=0;i<num_values;++i)
- {
- asprintf(data,"%s%s: %s\n", *data,name,value[i]);
- }
- else
- asprintf(data,"%s%s: \n", *data,name);
-
- free(tofree);
- return SPDY_YES;
-}
-
-
-static void
-standard_request_handler(void *cls,
- struct SPDY_Request * request,
- uint8_t priority,
- const char *method,
- const char *path,
- const char *version,
- const char *host,
- const char *scheme,
- struct SPDY_NameValue * headers,
- bool more)
-{
- (void)more;
-
- char *html;
- char *data;
- struct SPDY_Response *response=NULL;
-
- printf("received request for '%s %s %s'\n", method, path, version);
- if(strcmp(path,"/main.css")==0)
- {
- if(NULL != cls)
- asprintf(&html,"body{color:green;}");
- else
- asprintf(&html,"body{color:red;}");
-
- //struct SPDY_NameValue *headers=SPDY_name_value_create();
- //SPDY_name_value_add(headers,"content-type","text/css");
-
- response =
SPDY_build_response(200,NULL,SPDY_HTTP_VERSION_1_1,NULL,html,strlen(html));
- free(html);
- }
- else
- {
- asprintf(&data,"Priority: %i\nHTTP headers, scheme: %s\n\n%s %s
%s\nHost: %s\n", priority,scheme,method,path,version,host);
-
- SPDY_name_value_iterate(headers, &append_headers_to_data,
&data);
-
- if(strcmp(path,"/close")==0)
- {
- asprintf(&html,"<html>"
- "<body><b>Closing now!<br>This is an answer to the following "
- "request:</b><br><br><pre>%s</pre></body></html>",data);
- }
- else
- {
- asprintf(&html,"<html><link href=\"main.css\"
rel=\"stylesheet\" type=\"text/css\" />"
- "<body><b>This is an answer to the following "
- "request:</b><br><br><pre>%s</pre></body></html>",data);
- }
-
- free(data);
-
- response =
SPDY_build_response(200,NULL,SPDY_HTTP_VERSION_1_1,NULL,html,strlen(html));
- free(html);
- }
-
- if(NULL==response){
- fprintf(stdout,"no response obj\n");
- abort();
- }
-
- char *pathcls;
- asprintf(&pathcls, "%s (daemon%i)",path,NULL==cls ? 1 : 2);
-
if(SPDY_queue_response(request,response,true,false,&response_done_callback,pathcls)!=SPDY_YES)
- {
- fprintf(stdout,"queue\n");
- abort();
- }
-}
-
-
-static int
-new_post_data_cb (void * cls,
- struct SPDY_Request *request,
- const void * buf,
- size_t size,
- bool more)
-{
- (void)cls;
- (void)request;
- (void)more;
-
- printf("DATA:\n===============================\n");
- write(0, buf, size);
- printf("\n===============================\n");
- return SPDY_YES;
-}
-
-
-static void
-sig_handler(int signo)
-{
- (void)signo;
-
- printf("received signal\n");
-}
-
-
-int
-main (int argc, char *const *argv)
-{
- if(argc != 2) return 1;
-
- #ifndef MINGW
- if (signal(SIGPIPE, sig_handler) == SIG_ERR)
- printf("\ncan't catch SIGPIPE\n");
- #endif
-
- SPDY_init();
-
- /*
- struct sockaddr_in addr4;
- struct in_addr inaddr4;
- inaddr4.s_addr = htonl(INADDR_ANY);
- addr4.sin_family = AF_INET;
- addr4.sin_addr = inaddr4;
- addr4.sin_port = htons(atoi(argv[1]));
- */
-
- struct SPDY_Daemon *daemon = SPDY_start_daemon(atoi(argv[1]),
- DATA_DIR "cert-and-key.pem",
- DATA_DIR "cert-and-key.pem",
-
&new_session_callback,&session_closed_handler,&standard_request_handler,&new_post_data_cb,NULL,
- SPDY_DAEMON_OPTION_SESSION_TIMEOUT, 10,
- //SPDY_DAEMON_OPTION_SOCK_ADDR, (struct sockaddr *)&addr4,
- SPDY_DAEMON_OPTION_END);
-
- if(NULL==daemon){
- printf("no daemon\n");
- return 1;
- }
-
- /*
- struct sockaddr_in6 addr6;
- addr6.sin6_family = AF_INET6;
- addr6.sin6_addr = in6addr_any;
- addr6.sin6_port = htons(atoi(argv[1]) + 1);
- */
-
- struct SPDY_Daemon *daemon2 = SPDY_start_daemon(atoi(argv[1]) + 1,
- DATA_DIR "cert-and-key.pem",
- DATA_DIR "cert-and-key.pem",
-
&new_session_callback,NULL,&standard_request_handler,&new_post_data_cb,&main,
- //SPDY_DAEMON_OPTION_SESSION_TIMEOUT, 0,
- //SPDY_DAEMON_OPTION_SOCK_ADDR, (struct sockaddr *)&addr6,
- //SPDY_DAEMON_OPTION_FLAGS, SPDY_DAEMON_FLAG_ONLY_IPV6,
- SPDY_DAEMON_OPTION_END);
-
- if(NULL==daemon2){
- printf("no daemon\n");
- return 1;
- }
-
- do
- {
- unsigned long long timeoutlong=0;
- struct timeval timeout;
- volatile int rc; /* select() return code */
- volatile int ret;
-
- fd_set read_fd_set;
- fd_set write_fd_set;
- fd_set except_fd_set;
- int maxfd = -1;
-
- if(run && daemon != NULL)
- {
- loops++;
- FD_ZERO(&read_fd_set);
- FD_ZERO(&write_fd_set);
- FD_ZERO(&except_fd_set);
-
- ret = SPDY_get_timeout(daemon, &timeoutlong);
- if(SPDY_NO == ret || timeoutlong > 1000)
- {
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- }
- else
- {
- timeout.tv_sec = timeoutlong / 1000;
- timeout.tv_usec = (timeoutlong % 1000) * 1000;
- }
-
- printf("ret=%i; timeoutlong=%llu; sec=%llu; usec=%llu\n", ret,
timeoutlong, (long long unsigned)timeout.tv_sec, (long long
unsigned)timeout.tv_usec);
- //raise(SIGINT);
-
- /* get file descriptors from the transfers */
- maxfd = SPDY_get_fdset (daemon,
- &read_fd_set,
- &write_fd_set,
- &except_fd_set);
-
-//struct timeval ts1,ts2;
- //gettimeofday(&ts1, NULL);
- rc = select(maxfd+1, &read_fd_set, &write_fd_set,
&except_fd_set, &timeout);
- //gettimeofday(&ts2, NULL);
- printf("rc %i\n",rc);
- // printf("time for select %i\n",ts2.tv_usec - ts1.tv_usec);
- // printf("%i %i %i %i\n",ts1.tv_sec, ts1.tv_usec,ts2.tv_sec, ts2.tv_usec);
-
- switch(rc) {
- case -1:
- /* select error */
- break;
- case 0:
-
- break;
- default:
- SPDY_run(daemon);
-
- break;
- }
- }
- else if(daemon != NULL){
-
- printf("%lu loops in %llu secs\n", loops, (long long
unsigned)(time(NULL) - start));
- SPDY_stop_daemon(daemon);
- daemon=NULL;
- }
-
- if(run2)
- {
- FD_ZERO(&read_fd_set);
- FD_ZERO(&write_fd_set);
- FD_ZERO(&except_fd_set);
-
- ret = SPDY_get_timeout(daemon2, &timeoutlong);
- //printf("tout %i\n",timeoutlong);
- if(SPDY_NO == ret || timeoutlong > 1)
- {
- //do sth else
- //sleep(1);
-
- //try new connection
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- }
- else
- {
- timeout.tv_sec = timeoutlong;
- timeout.tv_usec = 0;//(timeoutlong % 1000) * 1000;
- }
-
- //printf("ret=%i; timeoutlong=%i; sec=%i; usec=%i\n", ret,
timeoutlong, timeout.tv_sec, timeout.tv_usec);
- //raise(SIGINT);
-
- /* get file descriptors from the transfers */
- maxfd = SPDY_get_fdset (daemon2,
- &read_fd_set,
- &write_fd_set,
- &except_fd_set);
-
- rc = select(maxfd+1, &read_fd_set, &write_fd_set,
&except_fd_set, &timeout);
-
- switch(rc) {
- case -1:
- /* select error */
- break;
- case 0:
-
- break;
- default:
- SPDY_run(daemon2);
-
- break;
- }
- }
- else if(daemon2 != NULL){
- SPDY_stop_daemon(daemon2);
- daemon2=NULL;
- }
- }
- while(run || run2);
-
- if(daemon != NULL){
- SPDY_stop_daemon(daemon);
- }
- if(daemon2 != NULL){
- SPDY_stop_daemon(daemon2);
- }
-
- SPDY_deinit();
-
- return 0;
-}
-
Deleted: libmicrohttpd/src/examples/spdy_fileserver.c
===================================================================
--- libmicrohttpd/src/examples/spdy_fileserver.c 2015-12-01 10:19:37 UTC
(rev 36707)
+++ libmicrohttpd/src/examples/spdy_fileserver.c 2015-12-01 13:06:38 UTC
(rev 36708)
@@ -1,353 +0,0 @@
-/*
- This file is part of libmicrospdy
- Copyright Copyright (C) 2013 Andrey Uzunov
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file fileserver.c
- * @brief Simple example how the lib can be used for serving
- * files directly read from the system
- * @author Andrey Uzunov
- */
-
-//for asprintf
-#define _GNU_SOURCE
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#include "microspdy.h"
-#include "time.h"
-
-
-int run = 1;
-char* basedir;
-
-
-#define GET_MIME_TYPE(fname, mime) do {\
- unsigned int __len = strlen(fname);\
- if (__len < 4 || '.' != (fname)[__len - 4]) \
- { \
- (mime) = strdup("application/octet-stream");\
- printf("MIME for %s is applic...\n", (fname));\
- }\
- else {\
- const char * __ext = &(fname)[__len - 3];\
- if(0 == strcmp(__ext, "jpg")) (mime) = strdup("image/jpeg");\
- else if(0 == strcmp(__ext, "png")) (mime) = strdup("image/png");\
- else if(0 == strcmp(__ext, "css")) (mime) = strdup("text/css");\
- else if(0 == strcmp(__ext, "gif")) (mime) = strdup("image/gif");\
- else if(0 == strcmp(__ext, "htm")) (mime) = strdup("text/html");\
- else \
- { \
- (mime) = strdup("application/octet-stream");\
- printf("MIME for %s is applic...\n", (fname));\
- }\
- }\
- if(NULL == (mime))\
- {\
- printf("no memory\n");\
- abort();\
- }\
- } while (0)
-
-
-static const char *DAY_NAMES[] =
- { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
-
-static const char *MONTH_NAMES[] =
- { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-//taken from
http://stackoverflow.com/questions/2726975/how-can-i-generate-an-rfc1123-date-string-from-c-code-win32
-//and modified for linux
-char *Rfc1123_DateTimeNow()
-{
- const int RFC1123_TIME_LEN = 29;
- time_t t;
- struct tm tm;
- char * buf = malloc(RFC1123_TIME_LEN+1);
-
- if (NULL == buf)
- return NULL;
- time(&t);
- gmtime_r( &t, &tm);
-
- strftime(buf, RFC1123_TIME_LEN+1, "---, %d --- %Y %H:%M:%S GMT", &tm);
- memcpy(buf, DAY_NAMES[tm.tm_wday], 3);
- memcpy(buf+8, MONTH_NAMES[tm.tm_mon], 3);
-
- return buf;
-}
-
-
-ssize_t
-response_callback (void *cls,
- void *buffer,
- size_t max,
- bool *more)
-{
- FILE *fd =(FILE*)cls;
-
- int ret = fread(buffer,1,max,fd);
- *more = feof(fd) == 0;
-
- //if(!(*more))
- // fclose(fd);
-
- return ret;
-}
-
-
-void
-response_done_callback(void *cls,
- struct SPDY_Response *response,
- struct SPDY_Request *request,
- enum SPDY_RESPONSE_RESULT
status,
- bool streamopened)
-{
- (void)streamopened;
- (void)status;
- //printf("answer for %s was sent\n", (char *)cls);
-
- /*if(SPDY_RESPONSE_RESULT_SUCCESS != status)
- {
- printf("answer for %s was NOT sent, %i\n", (char *)cls,status);
- }*/
-
- SPDY_destroy_request(request);
- SPDY_destroy_response(response);
- if(NULL!=cls)fclose(cls);
-}
-
-void
-standard_request_handler(void *cls,
- struct SPDY_Request * request,
- uint8_t priority,
- const char *method,
- const char *path,
- const char *version,
- const char *host,
- const char *scheme,
- struct SPDY_NameValue * headers,
- bool more)
-{
- (void)cls;
- (void)request;
- (void)priority;
- (void)host;
- (void)scheme;
- (void)headers;
- (void)method;
- (void)version;
- (void)more;
-
- struct SPDY_Response *response=NULL;
- struct SPDY_NameValue *resp_headers;
- char *fname;
- char *fsize;
- char *mime=NULL;
- char *date=NULL;
- ssize_t filesize = -666;
- FILE *fd = NULL;
- int ret = -666;
-
- //printf("received request for '%s %s %s'\n", method, path, version);
- if(strlen(path) > 1 && NULL == strstr(path, "..") && '/' == path[0])
- {
- asprintf(&fname,"%s%s",basedir,path);
- if(0 == access(fname, R_OK))
- {
- if(NULL == (fd = fopen(fname,"r"))
- || 0 != (ret = fseek(fd, 0L, SEEK_END))
- || -1 == (filesize = ftell(fd))
- || 0 != (ret = fseek(fd, 0L, SEEK_SET)))
- {
- printf("Error on opening %s\n%p %i
%zd\n",fname, fd, ret, filesize);
- response =
SPDY_build_response(SPDY_HTTP_INTERNAL_SERVER_ERROR,NULL,SPDY_HTTP_VERSION_1_1,NULL,NULL,0);
- }
- else
- {
- if(NULL == (resp_headers =
SPDY_name_value_create()))
- {
- printf("SPDY_name_value_create
failed\n");
- abort();
- }
-
- date = Rfc1123_DateTimeNow();
- if(NULL == date
- || SPDY_YES !=
SPDY_name_value_add(resp_headers,SPDY_HTTP_HEADER_DATE,date))
- {
- printf("SPDY_name_value_add or
Rfc1123_DateTimeNow failed\n");
- abort();
- }
- free(date);
-
- if(-1 == asprintf(&fsize, "%zd", filesize)
- || SPDY_YES !=
SPDY_name_value_add(resp_headers,SPDY_HTTP_HEADER_CONTENT_LENGTH,fsize))
- {
- printf("SPDY_name_value_add or asprintf
failed\n");
- abort();
- }
- free(fsize);
-
- GET_MIME_TYPE(path,mime);
- if(SPDY_YES !=
SPDY_name_value_add(resp_headers,SPDY_HTTP_HEADER_CONTENT_TYPE,mime))
- {
- printf("SPDY_name_value_add failed\n");
- abort();
- }
- free(mime);
-
- if(SPDY_YES !=
SPDY_name_value_add(resp_headers,SPDY_HTTP_HEADER_SERVER,"libmicrospdy/fileserver"))
- {
- printf("SPDY_name_value_add failed\n");
- abort();
- }
-
- response =
SPDY_build_response_with_callback(200,NULL,
-
SPDY_HTTP_VERSION_1_1,resp_headers,&response_callback,fd,SPDY_MAX_SUPPORTED_FRAME_SIZE);
- SPDY_name_value_destroy(resp_headers);
- }
-
- if(NULL==response){
- printf("no response obj\n");
- abort();
- }
-
-
if(SPDY_queue_response(request,response,true,false,&response_done_callback,fd)!=SPDY_YES)
- {
- printf("queue\n");
- abort();
- }
-
- free(fname);
- return;
- }
- free(fname);
- }
-
- if(strcmp(path,"/close")==0)
- {
- run = 0;
- }
-
- response =
SPDY_build_response(SPDY_HTTP_NOT_FOUND,NULL,SPDY_HTTP_VERSION_1_1,NULL,NULL,0);
- printf("Not found %s\n",path);
-
- if(NULL==response){
- printf("no response obj\n");
- abort();
- }
-
-
if(SPDY_queue_response(request,response,true,false,&response_done_callback,NULL)!=SPDY_YES)
- {
- printf("queue\n");
- abort();
- }
-}
-
-int
-main (int argc, char *const *argv)
-{
- unsigned long long timeoutlong=0;
- struct timeval timeout;
- int ret;
- fd_set read_fd_set;
- fd_set write_fd_set;
- fd_set except_fd_set;
- int maxfd = -1;
- struct SPDY_Daemon *daemon;
-
- if(argc != 5)
- {
- printf("Usage: %s cert-file key-file base-dir port\n", argv[0]);
- return 1;
- }
-
- SPDY_init();
-
- daemon = SPDY_start_daemon(atoi(argv[4]),
- argv[1],
- argv[2],
- NULL,
- NULL,
-
&standard_request_handler,
- NULL,
- NULL,
-
SPDY_DAEMON_OPTION_SESSION_TIMEOUT,
- 1800,
-
SPDY_DAEMON_OPTION_END);
-
- if(NULL==daemon){
- printf("no daemon\n");
- return 1;
- }
-
- basedir = argv[3];
-
- do
- {
- FD_ZERO(&read_fd_set);
- FD_ZERO(&write_fd_set);
- FD_ZERO(&except_fd_set);
-
- ret = SPDY_get_timeout(daemon, &timeoutlong);
- if(SPDY_NO == ret || timeoutlong > 1000)
- {
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- }
- else
- {
- timeout.tv_sec = timeoutlong / 1000;
- timeout.tv_usec = (timeoutlong % 1000) * 1000;
- }
-
- maxfd = SPDY_get_fdset (daemon,
- &read_fd_set,
- &write_fd_set,
- &except_fd_set);
-
- ret = select(maxfd+1, &read_fd_set, &write_fd_set,
&except_fd_set, &timeout);
-
- switch(ret) {
- case -1:
- printf("select error: %i\n", errno);
- break;
- case 0:
-
- break;
- default:
- SPDY_run(daemon);
-
- break;
- }
- }
- while(run);
-
- SPDY_stop_daemon(daemon);
-
- SPDY_deinit();
-
- return 0;
-}
-
Deleted: libmicrohttpd/src/examples/spdy_response_with_callback.c
===================================================================
--- libmicrohttpd/src/examples/spdy_response_with_callback.c 2015-12-01
10:19:37 UTC (rev 36707)
+++ libmicrohttpd/src/examples/spdy_response_with_callback.c 2015-12-01
13:06:38 UTC (rev 36708)
@@ -1,236 +0,0 @@
-/*
- This file is part of libmicrospdy
- Copyright Copyright (C) 2013 Andrey Uzunov
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file response_with_callback.c
- * @brief shows how to create responses with callbacks
- * @author Andrey Uzunov
- */
-
-//for asprintf
-#define _GNU_SOURCE
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#include "microspdy.h"
-
-static int run = 1;
-
-
-static ssize_t
-response_callback (void *cls,
- void *buffer,
- size_t max,
- bool *more)
-{
- FILE *fd =(FILE*)cls;
-
- int ret = fread(buffer,1,max,fd);
- *more = feof(fd) == 0;
-
- if(!(*more))
- fclose(fd);
-
- return ret;
-}
-
-
-static void
-response_done_callback(void *cls,
- struct SPDY_Response *response,
- struct SPDY_Request *request,
- enum SPDY_RESPONSE_RESULT status,
- bool streamopened)
-{
- (void)streamopened;
- (void)status;
-
- printf("answer for %s was sent\n", (char *)cls);
-
- SPDY_destroy_request(request);
- SPDY_destroy_response(response);
- free(cls);
-}
-
-
-static void
-standard_request_handler(void *cls,
- struct SPDY_Request * request,
- uint8_t priority,
- const char *method,
- const char *path,
- const char *version,
- const char *host,
- const char *scheme,
- struct SPDY_NameValue * headers,
- bool more)
-{
- (void)cls;
- (void)request;
- (void)priority;
- (void)host;
- (void)scheme;
- (void)headers;
- (void)more;
-
- char *html;
- struct SPDY_Response *response=NULL;
- struct SPDY_NameValue *resp_headers;
-
- printf("received request for '%s %s %s'\n", method, path, version);
- if(strcmp(path,"/spdy-draft.txt")==0)
- {
- FILE *fd = fopen(DATA_DIR "spdy-draft.txt","r");
-
- if(NULL == (resp_headers = SPDY_name_value_create()))
- {
- fprintf(stdout,"SPDY_name_value_create failed\n");
- abort();
- }
- if(SPDY_YES !=
SPDY_name_value_add(resp_headers,SPDY_HTTP_HEADER_CONTENT_TYPE,"text/plain"))
- {
- fprintf(stdout,"SPDY_name_value_add failed\n");
- abort();
- }
-
- response = SPDY_build_response_with_callback(200,NULL,
-
SPDY_HTTP_VERSION_1_1,resp_headers,&response_callback,fd,SPDY_MAX_SUPPORTED_FRAME_SIZE);
- SPDY_name_value_destroy(resp_headers);
- }
- else
- {
- if(strcmp(path,"/close")==0)
- {
- asprintf(&html,"<html>"
- "<body><b>Closing now!</body></html>");
- run = 0;
- }
- else
- {
- asprintf(&html,"<html>"
- "<body><a
href=\"/spdy-draft.txt\">/spdy-draft.txt</a><br></body></html>");
- }
-
- response =
SPDY_build_response(200,NULL,SPDY_HTTP_VERSION_1_1,NULL,html,strlen(html));
- free(html);
- }
-
- if(NULL==response){
- fprintf(stdout,"no response obj\n");
- abort();
- }
-
- void *clspath = strdup(path);
-
-
if(SPDY_queue_response(request,response,true,false,&response_done_callback,clspath)!=SPDY_YES)
- {
- fprintf(stdout,"queue\n");
- abort();
- }
-}
-
-
-int
-main (int argc, char *const *argv)
-{
- unsigned long long timeoutlong=0;
- struct timeval timeout;
- int ret;
- fd_set read_fd_set;
- fd_set write_fd_set;
- fd_set except_fd_set;
- int maxfd = -1;
- struct SPDY_Daemon *daemon;
-
- if(argc != 2)
- {
- return 1;
- }
-
- SPDY_init();
-
- daemon = SPDY_start_daemon(atoi(argv[1]),
- DATA_DIR
"cert-and-key.pem",
- DATA_DIR
"cert-and-key.pem",
- NULL,
- NULL,
-
&standard_request_handler,
- NULL,
- NULL,
-
SPDY_DAEMON_OPTION_SESSION_TIMEOUT,
- 1800,
-
SPDY_DAEMON_OPTION_END);
-
- if(NULL==daemon){
- printf("no daemon\n");
- return 1;
- }
-
- do
- {
- FD_ZERO(&read_fd_set);
- FD_ZERO(&write_fd_set);
- FD_ZERO(&except_fd_set);
-
- ret = SPDY_get_timeout(daemon, &timeoutlong);
- if(SPDY_NO == ret || timeoutlong > 1000)
- {
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- }
- else
- {
- timeout.tv_sec = timeoutlong / 1000;
- timeout.tv_usec = (timeoutlong % 1000) * 1000;
- }
-
- maxfd = SPDY_get_fdset (daemon,
- &read_fd_set,
- &write_fd_set,
- &except_fd_set);
-
- ret = select(maxfd+1, &read_fd_set, &write_fd_set,
&except_fd_set, &timeout);
-
- switch(ret) {
- case -1:
- printf("select error: %i\n", errno);
- break;
- case 0:
-
- break;
- default:
- SPDY_run(daemon);
-
- break;
- }
- }
- while(run);
-
- SPDY_stop_daemon(daemon);
-
- SPDY_deinit();
-
- return 0;
-}
-
Modified: libmicrohttpd/src/include/Makefile.am
===================================================================
--- libmicrohttpd/src/include/Makefile.am 2015-12-01 10:19:37 UTC (rev
36707)
+++ libmicrohttpd/src/include/Makefile.am 2015-12-01 13:06:38 UTC (rev
36708)
@@ -1,10 +1,6 @@
# This Makefile.am is in the public domain
SUBDIRS = .
-if ENABLE_SPDY
-microspdy = microspdy.h
-endif
+include_HEADERS = microhttpd.h
-include_HEADERS = microhttpd.h $(microspdy)
-
EXTRA_DIST = platform.h platform_interface.h w32functions.h autoinit_funcs.h
Deleted: libmicrohttpd/src/include/microspdy.h
===================================================================
--- libmicrohttpd/src/include/microspdy.h 2015-12-01 10:19:37 UTC (rev
36707)
+++ libmicrohttpd/src/include/microspdy.h 2015-12-01 13:06:38 UTC (rev
36708)
@@ -1,1380 +0,0 @@
-/*
- This file is part of libmicrospdy
- Copyright Copyright (C) 2012, 2013 Christian Grothoff
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file microspdy.h
- * @brief public interface to libmicrospdy
- * @author Andrey Uzunov
- * @author Christian Grothoff
- *
- * All symbols defined in this header start with SPDY_. libmisrospdy is a
small
- * SPDY daemon library. The application can start multiple daemons
- * and they are independent.<p>
- *
- * The header file defines various constants used by the SPDY and the HTTP
protocol.
- * This does not mean that the lib actually interprets all of these
- * values. Not everything is implemented. The provided constants are exported
as a convenience
- * for users of the library. The lib does not verify that provided
- * HTTP headers and if their values conform to the SPDY protocol,
- * it only checks if the required headers for the SPDY requests and
- * responses are provided.<p>
- *
- * The library uses just a single thread.<p>
- *
- * Before including "microspdy.h" you should add the necessary
- * includes to define the types used in this file (which headers are needed may
- * depend on your platform; for possible suggestions consult
- * "platform.h" in the libmicrospdy distribution).<p>
- *
- * All of the functions returning SPDY_YES/SPDY_NO return
- * SPDY_INPUT_ERROR when any of the parameters are invalid, e.g.
- * required parameter is NULL.<p>
- *
- * The library does not check if anything at the application layer --
- * requests and responses -- is correct. For example, it
- * is up to the user to check if a client is sending HTTP body but the
- * method is GET.<p>
- *
- * The SPDY flow control is just partially implemented: the receiving
- * window is updated, and the client is notified, to prevent a client
- * from stop sending POST body data, for example.
- */
-#ifndef SPDY_MICROSPDY_H
-#define SPDY_MICROSPDY_H
-
-#include <zlib.h>
-#include <stdbool.h>
-
-/* While we generally would like users to use a configure-driven
- build process which detects which headers are present and
- hence works on any platform, we use "standard" includes here
- to build out-of-the-box for beginning users on common systems.
-
- Once you have a proper build system and go for more exotic
- platforms, you should define MHD_PLATFORM_H in some header that
- you always include *before* "microhttpd.h". Then the following
- "standard" includes won't be used (which might be a good
- idea, especially on platforms where they do not exist). */
-#ifndef MHD_PLATFORM_H
-#include <unistd.h>
-#include <stdarg.h>
-#include <stdint.h>
-#ifdef __MINGW32__
-#include <ws2tcpip.h>
-#else
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif
-#endif
-
-#ifndef _MHD_EXTERN
-#define _MHD_EXTERN extern
-#endif
-
-/**
- * return code for "YES".
- */
-#define SPDY_YES 1
-
-/**
- * return code for "NO".
- */
-#define SPDY_NO 0
-
-/**
- * return code for error when input parameters are wrong. To be returned
- * only by functions which return int. The others will return NULL on
- * input error.
- */
-#define SPDY_INPUT_ERROR -1
-
-/**
- * SPDY version supported by the lib.
- */
-#define SPDY_VERSION 3
-
-/**
- * The maximum allowed size (without 8 byte headers) of
- * SPDY frames (value length) is 8192. The lib will accept and
- * send frames with length at most this value here.
- */
-#define SPDY_MAX_SUPPORTED_FRAME_SIZE 8192
-
-/**
- * HTTP response codes.
- */
-#define SPDY_HTTP_CONTINUE 100
-#define SPDY_HTTP_SWITCHING_PROTOCOLS 101
-#define SPDY_HTTP_PROCESSING 102
-
-#define SPDY_HTTP_OK 200
-#define SPDY_HTTP_CREATED 201
-#define SPDY_HTTP_ACCEPTED 202
-#define SPDY_HTTP_NON_AUTHORITATIVE_INFORMATION 203
-#define SPDY_HTTP_NO_CONTENT 204
-#define SPDY_HTTP_RESET_CONTENT 205
-#define SPDY_HTTP_PARTIAL_CONTENT 206
-#define SPDY_HTTP_MULTI_STATUS 207
-
-#define SPDY_HTTP_MULTIPLE_CHOICES 300
-#define SPDY_HTTP_MOVED_PERMANENTLY 301
-#define SPDY_HTTP_FOUND 302
-#define SPDY_HTTP_SEE_OTHER 303
-#define SPDY_HTTP_NOT_MODIFIED 304
-#define SPDY_HTTP_USE_PROXY 305
-#define SPDY_HTTP_SWITCH_PROXY 306
-#define SPDY_HTTP_TEMPORARY_REDIRECT 307
-
-#define SPDY_HTTP_BAD_REQUEST 400
-#define SPDY_HTTP_UNAUTHORIZED 401
-#define SPDY_HTTP_PAYMENT_REQUIRED 402
-#define SPDY_HTTP_FORBIDDEN 403
-#define SPDY_HTTP_NOT_FOUND 404
-#define SPDY_HTTP_METHOD_NOT_ALLOWED 405
-#define SPDY_HTTP_METHOD_NOT_ACCEPTABLE 406
-#define SPDY_HTTP_PROXY_AUTHENTICATION_REQUIRED 407
-#define SPDY_HTTP_REQUEST_TIMEOUT 408
-#define SPDY_HTTP_CONFLICT 409
-#define SPDY_HTTP_GONE 410
-#define SPDY_HTTP_LENGTH_REQUIRED 411
-#define SPDY_HTTP_PRECONDITION_FAILED 412
-#define SPDY_HTTP_REQUEST_ENTITY_TOO_LARGE 413
-#define SPDY_HTTP_REQUEST_URI_TOO_LONG 414
-#define SPDY_HTTP_UNSUPPORTED_MEDIA_TYPE 415
-#define SPDY_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE 416
-#define SPDY_HTTP_EXPECTATION_FAILED 417
-#define SPDY_HTTP_UNPROCESSABLE_ENTITY 422
-#define SPDY_HTTP_LOCKED 423
-#define SPDY_HTTP_FAILED_DEPENDENCY 424
-#define SPDY_HTTP_UNORDERED_COLLECTION 425
-#define SPDY_HTTP_UPGRADE_REQUIRED 426
-#define SPDY_HTTP_NO_RESPONSE 444
-#define SPDY_HTTP_RETRY_WITH 449
-#define SPDY_HTTP_BLOCKED_BY_WINDOWS_PARENTAL_CONTROLS 450
-#define SPDY_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS 451
-
-#define SPDY_HTTP_INTERNAL_SERVER_ERROR 500
-#define SPDY_HTTP_NOT_IMPLEMENTED 501
-#define SPDY_HTTP_BAD_GATEWAY 502
-#define SPDY_HTTP_SERVICE_UNAVAILABLE 503
-#define SPDY_HTTP_GATEWAY_TIMEOUT 504
-#define SPDY_HTTP_HTTP_VERSION_NOT_SUPPORTED 505
-#define SPDY_HTTP_VARIANT_ALSO_NEGOTIATES 506
-#define SPDY_HTTP_INSUFFICIENT_STORAGE 507
-#define SPDY_HTTP_BANDWIDTH_LIMIT_EXCEEDED 509
-#define SPDY_HTTP_NOT_EXTENDED 510
-
-/**
- * HTTP headers are used in SPDY, but all of them MUST be lowercase.
- * Some are not valid in SPDY and MUST not be used
- */
-#define SPDY_HTTP_HEADER_ACCEPT "accept"
-#define SPDY_HTTP_HEADER_ACCEPT_CHARSET "accept-charset"
-#define SPDY_HTTP_HEADER_ACCEPT_ENCODING "accept-encoding"
-#define SPDY_HTTP_HEADER_ACCEPT_LANGUAGE "accept-language"
-#define SPDY_HTTP_HEADER_ACCEPT_RANGES "accept-ranges"
-#define SPDY_HTTP_HEADER_AGE "age"
-#define SPDY_HTTP_HEADER_ALLOW "allow"
-#define SPDY_HTTP_HEADER_AUTHORIZATION "authorization"
-#define SPDY_HTTP_HEADER_CACHE_CONTROL "cache-control"
-/* Connection header is forbidden in SPDY */
-#define SPDY_HTTP_HEADER_CONNECTION "connection"
-#define SPDY_HTTP_HEADER_CONTENT_ENCODING "content-encoding"
-#define SPDY_HTTP_HEADER_CONTENT_LANGUAGE "content-language"
-#define SPDY_HTTP_HEADER_CONTENT_LENGTH "content-length"
-#define SPDY_HTTP_HEADER_CONTENT_LOCATION "content-location"
-#define SPDY_HTTP_HEADER_CONTENT_MD5 "content-md5"
-#define SPDY_HTTP_HEADER_CONTENT_RANGE "content-range"
-#define SPDY_HTTP_HEADER_CONTENT_TYPE "content-type"
-#define SPDY_HTTP_HEADER_COOKIE "cookie"
-#define SPDY_HTTP_HEADER_DATE "date"
-#define SPDY_HTTP_HEADER_ETAG "etag"
-#define SPDY_HTTP_HEADER_EXPECT "expect"
-#define SPDY_HTTP_HEADER_EXPIRES "expires"
-#define SPDY_HTTP_HEADER_FROM "from"
-/* Host header is forbidden in SPDY */
-#define SPDY_HTTP_HEADER_HOST "host"
-#define SPDY_HTTP_HEADER_IF_MATCH "if-match"
-#define SPDY_HTTP_HEADER_IF_MODIFIED_SINCE "if-modified-since"
-#define SPDY_HTTP_HEADER_IF_NONE_MATCH "if-none-match"
-#define SPDY_HTTP_HEADER_IF_RANGE "if-range"
-#define SPDY_HTTP_HEADER_IF_UNMODIFIED_SINCE "if-unmodified-since"
-/* Keep-Alive header is forbidden in SPDY */
-#define SPDY_HTTP_HEADER_KEEP_ALIVE "keep-alive"
-#define SPDY_HTTP_HEADER_LAST_MODIFIED "last-modified"
-#define SPDY_HTTP_HEADER_LOCATION "location"
-#define SPDY_HTTP_HEADER_MAX_FORWARDS "max-forwards"
-#define SPDY_HTTP_HEADER_PRAGMA "pragma"
-#define SPDY_HTTP_HEADER_PROXY_AUTHENTICATE "proxy-authenticate"
-#define SPDY_HTTP_HEADER_PROXY_AUTHORIZATION "proxy-authorization"
-/* Proxy-Connection header is forbidden in SPDY */
-#define SPDY_HTTP_HEADER_PROXY_CONNECTION "proxy-connection"
-#define SPDY_HTTP_HEADER_RANGE "range"
-#define SPDY_HTTP_HEADER_REFERER "referer"
-#define SPDY_HTTP_HEADER_RETRY_AFTER "retry-after"
-#define SPDY_HTTP_HEADER_SERVER "server"
-#define SPDY_HTTP_HEADER_SET_COOKIE "set-cookie"
-#define SPDY_HTTP_HEADER_SET_COOKIE2 "set-cookie2"
-#define SPDY_HTTP_HEADER_TE "te"
-#define SPDY_HTTP_HEADER_TRAILER "trailer"
-/* Transfer-Encoding header is forbidden in SPDY */
-#define SPDY_HTTP_HEADER_TRANSFER_ENCODING "transfer-encoding"
-#define SPDY_HTTP_HEADER_UPGRADE "upgrade"
-#define SPDY_HTTP_HEADER_USER_AGENT "user-agent"
-#define SPDY_HTTP_HEADER_VARY "vary"
-#define SPDY_HTTP_HEADER_VIA "via"
-#define SPDY_HTTP_HEADER_WARNING "warning"
-#define SPDY_HTTP_HEADER_WWW_AUTHENTICATE "www-authenticate"
-
-/**
- * HTTP versions (a value must be provided in SPDY requests/responses).
- */
-#define SPDY_HTTP_VERSION_1_0 "HTTP/1.0"
-#define SPDY_HTTP_VERSION_1_1 "HTTP/1.1"
-
-/**
- * HTTP methods
- */
-#define SPDY_HTTP_METHOD_CONNECT "CONNECT"
-#define SPDY_HTTP_METHOD_DELETE "DELETE"
-#define SPDY_HTTP_METHOD_GET "GET"
-#define SPDY_HTTP_METHOD_HEAD "HEAD"
-#define SPDY_HTTP_METHOD_OPTIONS "OPTIONS"
-#define SPDY_HTTP_METHOD_POST "POST"
-#define SPDY_HTTP_METHOD_PUT "PUT"
-#define SPDY_HTTP_METHOD_TRACE "TRACE"
-
-/**
- * HTTP POST encodings, see also
- * http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4
- */
-#define SPDY_HTTP_POST_ENCODING_FORM_URLENCODED
"application/x-www-form-urlencoded"
-#define SPDY_HTTP_POST_ENCODING_MULTIPART_FORMDATA "multipart/form-data"
-
-
-/**
- * Handle for the daemon (listening on a socket).
- */
-struct SPDY_Daemon;
-
-
-/**
- * Handle for a SPDY session/connection.
- */
-struct SPDY_Session;
-
-
-/**
- * Handle for a SPDY request sent by a client. The structure has pointer
- * to the session's handler
- */
-struct SPDY_Request;
-
-
-/**
- * Handle for a response containing HTTP headers and data to be sent.
- * The structure has pointer to the session's handler
- * for this response.
- */
-struct SPDY_Response;
-
-
-/**
- * Collection of tuples of an HTTP header and values used in requests
- * and responses.
- */
-struct SPDY_NameValue;
-
-
-/**
- * Collection of tuples of a SPDY setting ID, value
- * and flags used to control the sessions.
- */
-struct SPDY_Settings;
-
-
-/**
- * SPDY IO sybsystem flags used by SPDY_init() and SPDY_deinit().<p>
- *
- * The values are used internally as flags, that is why they must be
- * powers of 2.
- */
-enum SPDY_IO_SUBSYSTEM
-{
-
- /**
- * No subsystem. For internal use.
- */
- SPDY_IO_SUBSYSTEM_NONE = 0,
-
- /**
- * Default TLS implementation provided by openSSL/libssl.
- */
- SPDY_IO_SUBSYSTEM_OPENSSL = 1,
-
- /**
- * No TLS is used.
- */
- SPDY_IO_SUBSYSTEM_RAW = 2
-};
-
-
-/**
- * SPDY daemon options. Passed in the varargs portion of
- * SPDY_start_daemon to customize the daemon. Each option must
- * be followed by a value of a specific type.<p>
- *
- * The values are used internally as flags, that is why they must be
- * powers of 2.
- */
-enum SPDY_DAEMON_OPTION
-{
-
- /**
- * No more options / last option. This is used
- * to terminate the VARARGs list.
- */
- SPDY_DAEMON_OPTION_END = 0,
-
- /**
- * Set a custom timeout for all connections. Must be followed by
- * a number of seconds, given as an 'unsigned int'. Use
- * zero for no timeout.
- */
- SPDY_DAEMON_OPTION_SESSION_TIMEOUT = 1,
-
- /**
- * Bind daemon to the supplied sockaddr. This option must be
- * followed by a 'struct sockaddr *'. The 'struct sockaddr*'
- * should point to a 'struct sockaddr_in6' or to a
- * 'struct sockaddr_in'.
- */
- SPDY_DAEMON_OPTION_SOCK_ADDR = 2,
-
- /**
- * Flags for the daemon. Must be followed by a SPDY_DAEMON_FLAG value
- * which is the result of bitwise OR of desired flags.
- */
- SPDY_DAEMON_OPTION_FLAGS = 4,
-
- /**
- * IO subsystem type used by daemon and all its sessions. If not set,
- * TLS provided by openssl is used. Must be followed by a
- * SPDY_IO_SUBSYSTEM value.
- */
- SPDY_DAEMON_OPTION_IO_SUBSYSTEM = 8,
-
- /**
- * Maximum number of frames to be written to the socket at once. The
- * library tries to send max_num_frames in a single call to SPDY_run
- * for a single session. This means no requests can be received nor
- * other sessions can send data as long the current one has enough
- * frames to send and there is no error on writing. Thus, a big value
- * will affect the performance. Small value gives fairnes for sessions.
- * Must be followed by a positive integer (uin32_t). If not set, the
- * default value 10 will be used.
- */
- SPDY_DAEMON_OPTION_MAX_NUM_FRAMES = 16
-};
-
-
-/**
- * Flags for starting SPDY daemon. They are used to set some settings
- * for the daemon, which do not require values.
- */
-enum SPDY_DAEMON_FLAG
-{
- /**
- * No flags selected.
- */
- SPDY_DAEMON_FLAG_NO = 0,
-
- /**
- * The server will bind only on IPv6 addresses. If the flag is set and
- * the daemon is provided with IPv4 address or IPv6 is not supported,
- * starting daemon will fail.
- */
- SPDY_DAEMON_FLAG_ONLY_IPV6 = 1,
-
- /**
- * All sessions' sockets will be set with TCP_NODELAY if the flag is
- * used. Option considered only by SPDY_IO_SUBSYSTEM_RAW.
- */
- SPDY_DAEMON_FLAG_NO_DELAY = 2
-};
-
-
-/**
- * SPDY settings IDs sent by both client and server in SPDY SETTINGS frame.
- * They affect the whole SPDY session. Defined in SPDY Protocol - Draft 3.
- */
-enum SPDY_SETTINGS
-{
-
- /**
- * Allows the sender to send its expected upload bandwidth on this
- * channel. This number is an estimate. The value should be the
- * integral number of kilobytes per second that the sender predicts
- * as an expected maximum upload channel capacity.
- */
- SPDY_SETTINGS_UPLOAD_BANDWIDTH = 1,
-
- /**
- * Allows the sender to send its expected download bandwidth on this
- * channel. This number is an estimate. The value should be the
- * integral number of kilobytes per second that the sender predicts as
- * an expected maximum download channel capacity.
- */
- SPDY_SETTINGS_DOWNLOAD_BANDWIDTH = 2,
-
- /**
- * Allows the sender to send its expected round-trip-time on this
- * channel. The round trip time is defined as the minimum amount of
- * time to send a control frame from this client to the remote and
- * receive a response. The value is represented in milliseconds.
- */
- SPDY_SETTINGS_ROUND_TRIP_TIME = 3,
-
- /**
- * Allows the sender to inform the remote endpoint the maximum number
- * of concurrent streams which it will allow. By default there is no
- * limit. For implementors it is recommended that this value be no
- * smaller than 100.
- */
- SPDY_SETTINGS_MAX_CONCURRENT_STREAMS = 4,
-
- /**
- * Allows the sender to inform the remote endpoint of the current TCP
- * CWND value.
- */
- SPDY_SETTINGS_CURRENT_CWND = 5,
-
- /**
- * Allows the sender to inform the remote endpoint the retransmission
- * rate (bytes retransmitted / total bytes transmitted).
- */
- SPDY_SETTINGS_DOWNLOAD_RETRANS_RATE = 6,
-
- /**
- * Allows the sender to inform the remote endpoint the initial window
- * size (in bytes) for new streams.
- */
- SPDY_SETTINGS_INITIAL_WINDOW_SIZE = 7,
-
- /**
- * Allows the server to inform the client if the new size of the
- * client certificate vector.
- */
- SPDY_SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8
-};
-
-
-/**
- * Flags for each individual SPDY setting in the SPDY SETTINGS frame.
- * They affect only one setting to which they are set.
- * Defined in SPDY Protocol - Draft 3.
- */
-enum SPDY_FLAG_SETTINGS
-{
-
- /**
- * When set, the sender of this SETTINGS frame is requesting that the
- * recipient persist the ID/Value and return it in future SETTINGS
- * frames sent from the sender to this recipient. Because persistence
- * is only implemented on the client, this flag is only sent by the
- * server.
- */
- SPDY_FLAG_SETTINGS_PERSIST_VALUE = 1,
-
- /**
- * When set, the sender is notifying the recipient that this ID/Value
- * pair was previously sent to the sender by the recipient with the
- * #SPDY_FLAG_SETTINGS_PERSIST_VALUE, and the sender is returning it.
- * Because persistence is only implemented on the client, this flag is
- * only sent by the client.
- */
- SPDY_FLAG_SETTINGS_PERSISTED = 2
-};
-
-
-/**
- * Flag associated with a whole SPDY SETTINGS frame. Affect all the
- * settings in the frame. Defined in SPDY Protocol - Draft 3.
- */
-enum SPDY_FLAG_SETTINGS_FRAME
-{
-
- /**
- * When set, the client should clear any previously persisted SETTINGS
- * ID/Value pairs. If this frame contains ID/Value pairs with the
- * #SPDY_FLAG_SETTINGS_PERSIST_VALUE set, then the client will first
- * clear its existing, persisted settings, and then persist the values
- * with the flag set which are contained within this frame. Because
- * persistence is only implemented on the client, this flag can only
- * be used when the sender is the server.
- */
- SPDY_FLAG_SETTINGS_CLEAR_SETTINGS = 1
-};
-
-
-/**
- * SPDY settings function options. Passed in the varargs portion of
- * SPDY_SettingsReceivedCallback and SPDY_send_settings to customize
- * more the settings handling. Each option must
- * be followed by a value of a specific type.<p>
- *
- * The values are used internally as flags, that is why they must be
- * powers of 2.
- */
-enum SPDY_SETTINGS_OPTION
-{
-
- /**
- * No more options / last option. This is used
- * to terminate the VARARGs list.
- */
- SPDY_SETTINGS_OPTION_END = 0
-};
-
-
-/**
- * Used as a parameter for SPDY_ResponseResultCallback and shows if the
- * response was actually written to the TLS socket or discarded by the
- * lib for any reason (and respectively the reason).
- */
-enum SPDY_RESPONSE_RESULT
-{
-
- /**
- * The lib has written the full response to the TLS socket.
- */
- SPDY_RESPONSE_RESULT_SUCCESS = 0,
-
- /**
- * The session is being closed, so the data is being discarded
- */
- SPDY_RESPONSE_RESULT_SESSION_CLOSED = 1,
-
- /**
- * The stream for this response has been closed. May happen when the
- * sender had sent first SYN_STREAM and after that RST_STREAM.
- */
- SPDY_RESPONSE_RESULT_STREAM_CLOSED = 2
-};
-
-
-/**
- * Callback for serious error condition. The default action is to print
- * an error message and abort().
- *
- * @param cls user specified value
- * @param file where the error occured
- * @param line where the error occured
- * @param reason error details message, may be NULL
- */
-typedef void
-(*SPDY_PanicCallback) (void * cls,
- const char *file,
- unsigned int line,
- const char *reason);
-
-
-/**
- * Callback for new SPDY session established by a client. Called
- * immediately after the TCP connection was established.
- *
- * @param cls client-defined closure
- * @param session handler for the new SPDY session
- */
-typedef void
-(*SPDY_NewSessionCallback) (void * cls,
- struct SPDY_Session * session);
-
-
-/**
- * Callback for closed session. Called after the TCP connection was
- * closed. In this callback function the user has the last
- * chance to access the SPDY_Session structure. After that the latter
- * will be cleaned!
- *
- * @param cls client-defined closure
- * @param session handler for the closed SPDY session
- * @param by_client #SPDY_YES if the session close was initiated by the
- * client;
- * #SPDY_NO if closed by the server
- */
-typedef void
-(*SPDY_SessionClosedCallback) (void *cls,
- struct SPDY_Session *session,
- int by_client);
-
-
-/**
- * Iterator over name-value pairs.
- *
- * @param cls client-defined closure
- * @param name of the pair
- * @param value of the pair
- * @return #SPDY_YES to continue iterating,
- * #SPDY_NO to abort the iteration
- */
-typedef int
-(*SPDY_NameValueIterator) (void *cls,
- const char *name,
- const char * const * value,
- int num_values);
-
-
-/**
- * Callback for received SPDY request. The functions is called whenever
- * a reqest comes, but will also be called if more headers/trailers are
- * received.
- *
- * @param cls client-defined closure
- * @param request handler. The request object is required for
- * sending responses.
- * @param priority of the SPDY stream which the request was
- * sent over
- * @param method HTTP method
- * @param path HTTP path
- * @param version HTTP version just like in HTTP request/response:
- * "HTTP/1.0" or "HTTP/1.1" currently
- * @param host called host as in HTTP
- * @param scheme used ("http" or "https"). In SPDY 3 it is only "https".
- * @param headers other HTTP headers from the request
- * @param more a flag saying if more data related to the request is
- * expected to be received. HTTP body may arrive (e.g. POST data);
- * then SPDY_NewDataCallback will be called for the connection.
- * It is also possible that more headers/trailers arrive;
- * then the same callback will be invoked. The user should detect
- * that it is not the first invocation of the function for that
- * request.
- */
-typedef void
-(*SPDY_NewRequestCallback) (void *cls,
- struct SPDY_Request *request,
- uint8_t priority,
- const char *method,
- const char *path,
- const char *version,
- const char *host,
- const char *scheme,
- struct SPDY_NameValue *headers,
- bool more);
-
-
-/**
- * Callback for received new data chunk (HTTP body) from a given
- * request (e.g. POST data).
- *
- * @param cls client-defined closure
- * @param request handler
- * @param buf data chunk from the POST data
- * @param size the size of the data chunk 'buf' in bytes. Note that it
- * may be 0.
- * @param more false if this is the last chunk from the data. Note:
- * true does not mean that more data will come, exceptional
- * situation is possible
- * @return #SPDY_YES to continue calling the function,
- * #SPDY_NO to stop calling the function for this request
- */
-typedef int
-(*SPDY_NewDataCallback) (void *cls,
- struct SPDY_Request *request,
- const void *buf,
- size_t size,
- bool more);
-// How about passing POST encoding information
-// here as well?
-//TODO
-
-
-/**
- * Callback to be used with SPDY_build_response_with_callback. The
- * callback will be called when the lib wants to write to the TLS socket.
- * The application should provide the data to be sent.
- *
- * @param cls client-defined closure
- * @param max maximum number of bytes that are allowed to be written
- * to the buffer.
- * @param more true if more data will be sent (i.e. the function must
- * be calleed again),
- * false if this is the last chunk, the lib will close
- * the stream
- * @return number of bytes written to buffer. On error the call MUST
- * return value less than 0 to indicate the library.
- */
-typedef ssize_t
-(*SPDY_ResponseCallback) (void *cls,
- void *buffer,
- size_t max,
- bool *more);
-
-
-/**
- * Callback to be called when the last bytes from the response was sent
- * to the client or when the response was discarded from the lib. This
- * callback is a very good place to discard the request and the response
- * objects, if they will not be reused (e.g., sending the same response
- * again). If the stream is closed it is safe to discard the request
- * object.
- *
- * @param cls client-defined closure
- * @param response handler to the response that was just sent
- * @param request handler to the request for which the response was sent
- * @param status shows if actually the response was sent or it was
- * discarded by the lib for any reason (e.g., closing
session,
- * closing stream, stopping daemon, etc.). It is possible
that
- * status indicates an error but parts of the response
headers
- * and/or body (in one
- * or several frames) were already sent to the client.
- * @param streamopened indicates if the the stream for this request/
- * response pair is still opened. If yes, the server may
want
- * to use SPDY push to send something additional to the
client
- * and/or close the stream.
- */
-typedef void
-(*SPDY_ResponseResultCallback) (void * cls,
- struct SPDY_Response *response,
- struct SPDY_Request *request,
- enum SPDY_RESPONSE_RESULT status,
- bool streamopened);
-
-
-/**
- * Callback to notify when SPDY ping response is received.
- *
- * @param session handler for which the ping request was sent
- * @param rtt the timespan between sending ping request and receiving it
- * from the library
- */
-typedef void
-(*SPDY_PingCallback) (void * cls,
- struct SPDY_Session *session,
- struct timeval *rtt);
-
-
-/**
- * Iterator over settings ID/Value/Flags tuples.
- *
- * @param cls client-defined closure
- * @param id SPDY settings ID
- * @param value value for this setting
- * @param flags flags for this tuple; use
- * `enum SPDY_FLAG_SETTINGS`
- * @return #SPDY_YES to continue iterating,
- * #SPDY_NO to abort the iteration
- */
-typedef int
-(*SPDY_SettingsIterator) (void *cls,
- enum SPDY_SETTINGS id,
- int32_t value,
- uint8_t flags);
-
-
-/**
- * Callback to notify when SPDY SETTINGS are received from the client.
- *
- * @param session handler for which settings are received
- * @param settings ID/value/flags tuples of the settings
- * @param flags for the whole settings frame; use
- * enum SPDY_FLAG_SETTINGS_FRAME
- * @param ... list of options (type-value pairs,
- * terminated with #SPDY_SETTINGS_OPTION_END).
- */
-typedef void
-(*SPDY_SettingsReceivedCallback) (struct SPDY_Session *session,
- struct SPDY_Settings *settings,
- uint8_t flags,
- ...);
-
-
-/* Global functions for the library */
-
-
-/**
- * Init function for the whole library. It MUST be called before any
- * other function of the library to initialize things like TLS context
- * and possibly other stuff needed by the lib. Currently the call
- * always returns #SPDY_YES.
- *
- * @param io_subsystem the IO subsystem that will
- * be initialized. Several can be used with bitwise OR. If no
- * parameter is set, the default openssl subsystem will be used.
- * @return #SPDY_YES if the library was correctly initialized and its
- * functions can be used now;
- * #SPDY_NO on error
- */
-_MHD_EXTERN int
-(SPDY_init) (enum SPDY_IO_SUBSYSTEM io_subsystem, ...);
-#define SPDY_init() SPDY_init (SPDY_IO_SUBSYSTEM_OPENSSL)
-
-
-/**
- * Deinit function for the whole lib. It can be called after finishing
- * using the library. It frees and cleans up resources allocated in
- * SPDY_init. Currently the function does not do anything.
- */
-_MHD_EXTERN void
-SPDY_deinit (void);
-
-
-/**
- * Sets the global error handler to a different implementation. "cb"
- * will only be called in the case of typically fatal, serious
- * internal consistency issues. These issues should only arise in the
- * case of serious memory corruption or similar problems with the
- * architecture as well as failed assertions. While "cb" is allowed to
- * return and the lib will then try to continue, this is never safe.
- *
- * The default implementation that is used if no panic function is set
- * simply prints an error message and calls "abort". Alternative
- * implementations might call "exit" or other similar functions.
- *
- * @param cb new error handler
- * @param cls passed to error handler
- */
-_MHD_EXTERN void
-SPDY_set_panic_func (SPDY_PanicCallback cb,
- void *cls);
-
-
-/* Daemon functions */
-
-
-/**
- * Start a SPDY webserver on the given port.
- *
- * @param port to bind to. The value is ignored if address structure
- * is passed as daemon option
- * @param certfile path to the certificate that will be used by server
- * @param keyfile path to the keyfile for the certificate
- * @param nscb callback called when a new SPDY session is
- * established by a client
- * @param sccb callback called when a session is closed
- * @param nrcb callback called when a client sends request
- * @param npdcb callback called when HTTP body (POST data) is received
- * after request
- * @param cls common extra argument to all of the callbacks
- * @param ... list of options (type-value pairs,
- * terminated with #SPDY_DAEMON_OPTION_END).
- * @return NULL on error, handle to daemon on success
- */
-_MHD_EXTERN struct SPDY_Daemon *
-SPDY_start_daemon (uint16_t port,
- const char *certfile,
- const char *keyfile,
- SPDY_NewSessionCallback nscb,
- SPDY_SessionClosedCallback sccb,
- SPDY_NewRequestCallback nrcb,
- SPDY_NewDataCallback npdcb,
- void *cls,
- ...);
-
-
-/**
- * Shutdown the daemon. First all sessions are closed. It is NOT safe
- * to call this function in user callbacks.
- *
- * @param daemon to stop
- */
-_MHD_EXTERN void
-SPDY_stop_daemon (struct SPDY_Daemon *daemon);
-
-
-/**
- * Obtain the select sets for this daemon. Only those are retrieved,
- * which some processing should be done for, i.e. not all sockets are
- * added to write_fd_set.<p>
- *
- * It is possible that there is
- * nothing to be read from a socket but there is data either in the
- * TLS subsystem's read buffers or in libmicrospdy's read buffers, which
- * waits for being processed. In such case the file descriptor will be
- * added to write_fd_set. Since it is very likely for the socket to be
- * ready for writing, the select used in the application's event loop
- * will return with success, SPDY_run will be called, the data will be
- * processed and maybe something will be written to the socket. Without
- * this behaviour, considering a proper event loop, data may stay in the
- * buffers, but run is never called.
- *
- * @param daemon to get sets from
- * @param read_fd_set read set
- * @param write_fd_set write set
- * @param except_fd_set except set
- * @return largest FD added to any of the sets
- */
-_MHD_EXTERN int
-SPDY_get_fdset (struct SPDY_Daemon *daemon,
- fd_set *read_fd_set,
- fd_set *write_fd_set,
- fd_set *except_fd_set);
-
-
-/**
- * Obtain timeout value for select for this daemon. The returned value
- * is how long select
- * should at most block, not the timeout value set for connections.
- *
- * @param daemon to query for timeout
- * @param timeout will be set to the timeout value (in milliseconds)
- * @return #SPDY_YES on success
- * #SPDY_NO if no connections exist that
- * would necessiate the use of a timeout right now
- */
-_MHD_EXTERN int
-SPDY_get_timeout (struct SPDY_Daemon *daemon,
- unsigned long long *timeout);
-
-
-/**
- * Run webserver operations. This method must be called in
- * the client event loop.
- *
- * @param daemon to run
- */
-_MHD_EXTERN void
-SPDY_run (struct SPDY_Daemon *daemon);
-
-
-/* SPDY Session handling functions */
-
-
-/**
- * Closes a SPDY session. SPDY clients and servers are expected to keep
- * sessions opened as long as possible. However, the server may want to
- * close some connections, e.g. if there are too many, to free some
- * resources. The function can also be used to close a specific session
- * if the client is not desired.
- *
- * @param session handler to be closed
- */
-_MHD_EXTERN void
-SPDY_close_session (struct SPDY_Session * session);
-
-
-/**
- * Associate a void pointer with a session. The data accessible by the
- * pointer can later be used wherever the session handler is available.
- *
- * @param session handler
- * @param cls any data pointed by a pointer to be accessible later
- */
-_MHD_EXTERN void
-SPDY_set_cls_to_session (struct SPDY_Session *session,
- void *cls);
-
-
-/**
- * Retrieves the pointer associated with SPDY_set_cls_to_session().
- *
- * @param session handler to get its cls
- * @return same pointer added by SPDY_set_cls_to_session() or
- * NULL when nothing was associated
- */
-_MHD_EXTERN void *
-SPDY_get_cls_from_session (struct SPDY_Session *session);
-
-
-/**
- * Retrieves the remote address of a given session.
- *
- * @param session handler to get its remote address
- * @param addr out parameter; pointing to remote address
- * @return length of the address structure
- */
-_MHD_EXTERN socklen_t
-SPDY_get_remote_addr (struct SPDY_Session *session,
- struct sockaddr **addr);
-
-
-/* SPDY name/value data structure handling functions */
-
-
-/**
- * Create a new NameValue structure. It is needed for putting inside the
- * HTTP headers and their values for a response. The user should later
- * destroy alone the structure.
- *
- * @return handler to the new empty structure or NULL on error
- */
-_MHD_EXTERN struct SPDY_NameValue *
-SPDY_name_value_create (void);
-
-
-/**
- * Add name/value pair to a NameValue structure. SPDY_NO will be returned
- * if the name/value pair is already in the structure. It is legal to
- * add different values for the same name.
- *
- * @param container structure to which the new pair is added
- * @param name for the value. Null-terminated string.
- * @param value the value itself. Null-terminated string.
- * @return #SPDY_NO on error or #SPDY_YES on success
- */
-_MHD_EXTERN int
-SPDY_name_value_add (struct SPDY_NameValue *container,
- const char *name,
- const char *value);
-
-
-/**
- * Lookup value for a name in a name/value structure.
- *
- * @param container structure in which to lookup
- * @param name the name to look for
- * @param num_values length of the returned array with values
- * @return NULL if no such item was found, or an array containing the
- * values
- */
-_MHD_EXTERN const char * const *
-SPDY_name_value_lookup (struct SPDY_NameValue *container,
- const char *name,
- int *num_values);
-
-
-/**
- * Iterate over name/value structure.
- *
- * @param container structure which to iterate over
- * @param iterator callback to call on each name/value pair;
- * maybe NULL (then just count headers)
- * @param iterator_cls extra argument to @a iterator
- * @return number of entries iterated over
- */
-_MHD_EXTERN int
-SPDY_name_value_iterate (struct SPDY_NameValue *container,
- SPDY_NameValueIterator iterator,
- void *iterator_cls);
-
-
-/**
- * Destroy a NameValue structure. Use this function to destroy only
- * objects which, after passed to, will not be destroied by other
- * functions.
- *
- */
-_MHD_EXTERN void
-SPDY_name_value_destroy (struct SPDY_NameValue *container);
-
-
-/* SPDY request handling functions */
-
-
-/**
- * Gets the session responsible for the given
- * request.
- *
- * @param request for which the session is wanted
- * @return session handler for the request
- */
-_MHD_EXTERN struct SPDY_Session *
-SPDY_get_session_for_request (const struct SPDY_Request *request);
-
-
-/**
- * Associate a void pointer with a request. The data accessible by the
- * pointer can later be used wherever the request handler is available.
- *
- * @param request with which to associate a pointer
- * @param cls any data pointed by a pointer to be accessible later
- */
-_MHD_EXTERN void
-SPDY_set_cls_to_request (struct SPDY_Request *request,
- void *cls);
-
-
-/**
- * Retrieves the pointer associated with the request by
- * SPDY_set_cls_to_request().
- *
- * @param request to get its cls
- * @return same pointer added by SPDY_set_cls_to_request() or
- * NULL when nothing was associated
- */
-_MHD_EXTERN void *
-SPDY_get_cls_from_request (struct SPDY_Request *request);
-
-
-/* SPDY response handling functions */
-
-
-/**
- * Create response object containing all needed headers and data. The
- * response object is not bound to a request, so it can be used multiple
- * times with SPDY_queue_response() and schould be
- * destroied by calling the SPDY_destroy_response().<p>
- *
- * Currently the library does not provide compression of the body data.
- * It is up to the user to pass already compressed data and the
- * appropriate headers to this function when desired.
- *
- * @param status HTTP status code for the response (e.g. 404)
- * @param statustext HTTP status message for the response, which will
- * be appended to the status code (e.g. "OK"). Can be NULL
- * @param version HTTP version for the response (e.g. "http/1.1")
- * @param headers name/value structure containing additional HTTP headers.
- * Can be NULL. Can be used multiple times, it is up to
- * the user to destoy the object when not needed anymore.
- * @param data the body of the response. The lib will make a copy of it,
- * so it is up to the user to take care of the memory
- * pointed by data
- * @param size length of @a data. It can be 0, then the lib will send only
- * headers
- * @return NULL on error, handle to response object on success
- */
-_MHD_EXTERN struct SPDY_Response *
-SPDY_build_response (int status,
- const char *statustext,
- const char *version,
- struct SPDY_NameValue *headers,
- const void *data,
- size_t size);
-
-
-/**
- * Create response object containing all needed headers. The data will
- * be provided later when the lib calls the callback function (just
- * before writing it to the TLS socket). The
- * response object is not bound to a request, so it can be used multiple
- * times with SPDY_queue_response() and schould be
- * destroied by calling the SPDY_destroy_response().<p>
- *
- * Currently the library does not provide compression of the body data.
- * It is up to the user to pass already compressed data and the
- * appropriate headers to this function and the callback when desired.
- *
- * @param status HTTP status code for the response (e.g. 404)
- * @param statustext HTTP status message for the response, which will
- * be appended to the status code (e.g. "OK"). Can be NULL
- * @param version HTTP version for the response (e.g. "http/1.1")
- * @param headers name/value structure containing additional HTTP headers.
- * Can be NULL. Can be used multiple times, it is up to
- * the user to destoy the object when not needed anymore.
- * @param rcb callback to use to obtain response data
- * @param rcb_cls extra argument to @a rcb
- * @param block_size preferred block size for querying rcb (advisory only,
- * the lib will call rcb specifying the block size); clients
- * should pick a value that is appropriate for IO and
- * memory performance requirements. The function will
- * fail if the value is bigger than the maximum
- * supported value (SPDY_MAX_SUPPORTED_FRAME_SIZE).
- * Can be 0, then the lib will use
- * #SPDY_MAX_SUPPORTED_FRAME_SIZE instead.
- * @return NULL on error, handle to response object on success
- */
-_MHD_EXTERN struct SPDY_Response *
-SPDY_build_response_with_callback(int status,
- const char *statustext,
- const char *version,
- struct SPDY_NameValue *headers,
- SPDY_ResponseCallback rcb,
- void *rcb_cls,
- uint32_t block_size);
-
-
-/**
- * Queue response object to be sent to the client. A successfully queued
- * response may never be sent, e.g. when the stream gets closed. The
- * data will be added to the output queue. The call will fail, if the
- * output for this session
- * is closed (i.e. the session is closed, half or full) or the output
- * channel for the stream, on which the request was received, is closed
- * (i.e. the stream is closed, half or full).
- *
- * @param request object identifying the request to which the
- * response is returned
- * @param response object containg headers and data to be sent
- * @param closestream TRUE if the server does NOT intend to PUSH
- * something more associated to this request/response
later,
- * FALSE otherwise
- * @param consider_priority if FALSE, the response will be added to the
- * end of the queue. If TRUE, the response will be added
after
- * the last previously added response with priority of the
- * request grater or equal to that of the current one. This
- * means that the function should be called with TRUE each
time
- * if one wants to be sure that the output queue behaves
like
- * a priority queue
- * @param rrcb callback called when all the data was sent (last frame
- * from response) or when that frame was discarded (e.g.
the
- * stream has been closed meanwhile)
- * @param rrcb_cls extra argument to @a rrcb
- * @return #SPDY_NO on error or #SPDY_YES on success
- */
-_MHD_EXTERN int
-SPDY_queue_response (struct SPDY_Request *request,
- struct SPDY_Response *response,
- bool closestream,
- bool consider_priority,
- SPDY_ResponseResultCallback rrcb,
- void *rrcb_cls);
-
-
-/**
- * Destroy a response structure. It should be called for all objects
- * returned by SPDY_build_response*() functions to free the memory
- * associated with the prepared response. It is safe to call this
- * function not before being sure that the response will not be used by
- * the lib anymore, this means after SPDY_ResponseResultCallback
- * callbacks were called for all calls to SPDY_queue_response() passing
- * this response.
- *
- * @param response to destroy
- */
-_MHD_EXTERN void
-SPDY_destroy_response (struct SPDY_Response *response);
-
-
-/* SPDY settings ID/value data structure handling functions */
-
-
-/**
- * Create a new SettingsIDValue structure. It is needed for putting
- * inside tuples of SPDY option, flags and value for sending to the
- * client.
- *
- * @return hendler to the new empty structure or NULL on error
- */
-_MHD_EXTERN const struct SPDY_Settings *
-SPDY_settings_create (void);
-
-
-/**
- * Add or update a tuple to a SettingsIDValue structure.
- *
- * @param container structure to which the new tuple is added
- * @param id SPDY settings ID that will be sent. If this ID already in
- * container, the tupple for it will be updated (value and/or
- * flags). If it is not in the container, a new tupple will be
- * added.
- * @param flags SPDY settings flags applied only to this setting
- * @param value of the setting
- * @return #SPDY_NO on error
- * or #SPDY_YES if a new setting was added
- */
-_MHD_EXTERN int
-SPDY_settings_add (struct SPDY_Settings *container,
- enum SPDY_SETTINGS id,
- enum SPDY_FLAG_SETTINGS flags,
- int32_t value);
-
-
-/**
- * Lookup value and flags for an ID in a settings ID/value structure.
- *
- * @param container structure in which to lookup
- * @param id SPDY settings ID to search for
- * @param flags out param for SPDY settings flags for this setting;
- * check it against the flags in enum SPDY_FLAG_SETTINGS
- * @param value out param for the value of this setting
- * @return #SPDY_NO if the setting is not into the structure
- * or #SPDY_YES if it is into it
- */
-_MHD_EXTERN int
-SPDY_settings_lookup (const struct SPDY_Settings *container,
- enum SPDY_SETTINGS id,
- enum SPDY_FLAG_SETTINGS *flags,
- int32_t *value);
-
-
-/**
- * Iterate over settings ID/value structure.
- *
- * @param container structure which to iterate over
- * @param iterator callback to call on each ID/value pair;
- * maybe NULL (then just count number of settings)
- * @param iterator_cls extra argument to iterator
- * @return number of entries iterated over
- */
-_MHD_EXTERN int
-SPDY_settings_iterate (const struct SPDY_Settings *container,
- SPDY_SettingsIterator iterator,
- void *iterator_cls);
-
-
-/**
- * Destroy a settings ID/value structure. Use this function to destroy
- * only objects which, after passed to, will not be destroied by other
- * functions.
- *
- * @param container structure which to detroy
- */
-_MHD_EXTERN void
-SPDY_settings_destroy (struct SPDY_Settings * container);
-
-
-/* SPDY SETTINGS handling functions */
-
-
-/**
- * Send SPDY SETTINGS to the client. The call will return fail if there
- * in invald setting into the settings container (e.g. invalid setting
- * ID).
- *
- * @param session SPDY_Session handler for which settings are being sent
- * @param settings ID/value pairs of the settings to be sent.
- * Can be used multiple times, it is up to the user to
destoy
- * the object when not needed anymore.
- * @param flags for the whole settings frame. They are valid for all tuples
- * @param ... list of options (type-value pairs,
- * terminated with #SPDY_SETTINGS_OPTION_END).
- * @return SPDY_NO on error or SPDY_YES on
- * success
- */
-_MHD_EXTERN int
-SPDY_send_settings (struct SPDY_Session *session,
- struct SPDY_Settings *settings,
- enum SPDY_FLAG_SETTINGS_FRAME flags,
- ...);
-
-
-/* SPDY misc functions */
-
-
-/**
- * Destroy a request structure. It should be called for all objects
- * received as a parameter in SPDY_NewRequestCallback to free the memory
- * associated with the request. It is safe to call this
- * function not before being sure that the request will not be used by
- * the lib anymore, this means after the stream, on which this request
- * had been sent, was closed and all SPDY_ResponseResultCallback
- * callbacks were called for all calls to SPDY_queue_response() passing
- * this request object.
- *
- * @param request to destroy
- */
-_MHD_EXTERN void
-SPDY_destroy_request (struct SPDY_Request * request);
-
-
-/**
- * Send SPDY ping to the client
- *
- * @param session handler for which the ping request is sent
- * @param rttcb callback called when ping response to the request is
- * received
- * @param rttcb_cls extra argument to @a rttcb
- * @return #SPDY_NO on error or #SPDY_YES on success
- */
-_MHD_EXTERN int
-SPDY_send_ping (struct SPDY_Session *session,
- SPDY_PingCallback rttcb,
- void *rttcb_cls);
-
-#endif
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r36708 - in libmicrohttpd: . m4 src src/datadir src/examples src/include,
gnunet <=