aboutsummaryrefslogtreecommitdiff
path: root/src/include/microspdy.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/microspdy.h')
-rw-r--r--src/include/microspdy.h1380
1 files changed, 1380 insertions, 0 deletions
diff --git a/src/include/microspdy.h b/src/include/microspdy.h
new file mode 100644
index 00000000..7da5fbe6
--- /dev/null
+++ b/src/include/microspdy.h
@@ -0,0 +1,1380 @@
+/*
+ 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