spdylay.h 29.8 KB
Newer Older
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * Spdylay - SPDY Library
 *
 * Copyright (c) 2012 Tatsuhiro Tsujikawa
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#ifndef SPDYLAY_H
#define SPDYLAY_H

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
28 29 30 31
#ifdef  __cplusplus
extern "C" {
#endif

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
32
#include <stdlib.h>
33
#include <stdint.h>
Jim Morrison's avatar
Jim Morrison committed
34
#include <sys/types.h>
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
35

36 37
#include <spdylay/spdylayver.h>

38 39 40
struct spdylay_session;
typedef struct spdylay_session spdylay_session;

41
/* SPDY protocol version 2 */
42 43 44
#define SPDYLAY_PROTO_SPDY2 2
/* SPDY protocol version 3 */
#define SPDYLAY_PROTO_SPDY3 3
45

46 47
typedef enum {
  SPDYLAY_ERR_INVALID_ARGUMENT = -501,
48
  SPDYLAY_ERR_ZLIB = -502,
49
  SPDYLAY_ERR_UNSUPPORTED_VERSION = -503,
50 51
  SPDYLAY_ERR_WOULDBLOCK = -504,
  SPDYLAY_ERR_PROTO = -505,
52
  SPDYLAY_ERR_INVALID_FRAME = -506,
53
  SPDYLAY_ERR_EOF = -507,
54
  SPDYLAY_ERR_DEFERRED = -508,
55 56
  /* Stream ID has reached maximum value. Therefore no stream ID is
     available. */
57
  SPDYLAY_ERR_STREAM_ID_NOT_AVAILABLE = -509,
58 59 60 61
  /* The stream is already closed or it does not exist. */
  SPDYLAY_ERR_STREAM_CLOSED = -510,
  /* RST_STREAM has been queued in outbound queue. The stream is in
     closing state. */
62
  SPDYLAY_ERR_STREAM_CLOSING = -511,
63 64
  /* The transmission is not allowed for this stream (e.g., a frame
     with FIN flag set has already sent) */
65
  SPDYLAY_ERR_STREAM_SHUT_WR = -512,
66
  /* The stream ID is invalid. */
67
  SPDYLAY_ERR_INVALID_STREAM_ID = -513,
68 69
  /* The state of the stream is not valid (e.g., SYN_REPLY cannot be
     sent to the stream where SYN_REPLY has been already sent). */
70
  SPDYLAY_ERR_INVALID_STREAM_STATE = -514,
71
  /* Another DATA frame has already been deferred. */
72
  SPDYLAY_ERR_DEFERRED_DATA_EXIST = -515,
73 74
  /* SYN_STREAM is not allowed. (e.g., GOAWAY has been sent and/or
     received. */
75
  SPDYLAY_ERR_SYN_STREAM_NOT_ALLOWED = -516,
76
  /* GOAWAY has been already sent. */
77
  SPDYLAY_ERR_GOAWAY_ALREADY_SENT = -517,
78 79 80 81 82 83
  /* The errors < SPDYLAY_ERR_FATAL mean that the library is under
     unexpected condition that it cannot process any further data
     reliably (e.g., out of memory). */
  SPDYLAY_ERR_FATAL = -900,
  SPDYLAY_ERR_NOMEM = -901,
  SPDYLAY_ERR_CALLBACK_FAILURE = -902,
84 85 86 87 88 89
} spdylay_error;

typedef enum {
  SPDYLAY_MSG_MORE
} spdylay_io_flag;

90 91 92 93 94 95 96 97
typedef enum {
  SPDYLAY_SYN_STREAM = 1,
  SPDYLAY_SYN_REPLY = 2,
  SPDYLAY_RST_STREAM = 3,
  SPDYLAY_SETTINGS = 4,
  SPDYLAY_NOOP = 5,
  SPDYLAY_PING = 6,
  SPDYLAY_GOAWAY = 7,
98
  SPDYLAY_HEADERS = 8,
99 100
  /* Since SPDY/3 */
  SPDYLAY_WINDOW_UPDATE = 9,
101
  SPDYLAY_DATA = 100,
102 103 104
} spdylay_frame_type;

typedef enum {
105 106 107 108 109 110 111 112 113
  SPDYLAY_CTRL_FLAG_NONE = 0,
  SPDYLAY_CTRL_FLAG_FIN = 0x1,
  SPDYLAY_CTRL_FLAG_UNIDIRECTIONAL = 0x2
} spdylay_ctrl_flag;

typedef enum {
  SPDYLAY_DATA_FLAG_NONE = 0,
  SPDYLAY_DATA_FLAG_FIN = 0x1
} spdylay_data_flag;
114

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
typedef enum {
  SPDYLAY_FLAG_SETTINGS_NONE = 0,
  SPDYLAY_FLAG_SETTINGS_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 1
} spdylay_settings_flag;

typedef enum {
  SPDYLAY_ID_FLAG_SETTINGS_NONE = 0,
  SPDYLAY_ID_FLAG_SETTINGS_PERSIST_VALUE = 1,
  SPDYLAY_ID_FLAG_SETTINGS_PERSISTED = 2
} spdylay_settings_id_flag;

typedef enum {
  SPDYLAY_SETTINGS_UPLOAD_BANDWIDTH = 1,
  SPDYLAY_SETTINGS_DOWNLOAD_BANDWIDTH = 2,
  SPDYLAY_SETTINGS_ROUND_TRIP_TIME = 3,
  SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS = 4,
  SPDYLAY_SETTINGS_CURRENT_CWND = 5,
  SPDYLAY_SETTINGS_DOWNLOAD_RETRANS_RATE = 6,
  SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE = 7
} spdylay_settings_id;

136 137 138 139 140 141
/* Maximum ID of spdylay_settings_id. */
#define SPDYLAY_SETTINGS_MAX 7

/* Default maximum concurrent streams */
#define SPDYLAY_CONCURRENT_STREAMS_MAX 100

142
/* Status code for RST_STREAM */
143
typedef enum {
144 145
  /* SPDYLAY_OK is not valid status code for RST_STREAM. It is defined
     just for spdylay library use. */
146
  SPDYLAY_OK = 0,
147 148 149 150 151 152
  SPDYLAY_PROTOCOL_ERROR = 1,
  SPDYLAY_INVALID_STREAM = 2,
  SPDYLAY_REFUSED_STREAM = 3,
  SPDYLAY_UNSUPPORTED_VERSION = 4,
  SPDYLAY_CANCEL = 5,
  SPDYLAY_INTERNAL_ERROR = 6,
153 154 155 156 157 158
  SPDYLAY_FLOW_CONTROL_ERROR = 7,
  /* Following status codes were introduced in SPDY/3 */
  SPDYLAY_STREAM_IN_USE = 8,
  SPDYLAY_STREAM_ALREADY_CLOSED = 9,
  SPDYLAY_INVALID_CREDENTIALS = 10,
  FRAME_TOO_LARGE = 11
159 160
} spdylay_status_code;

161 162 163 164 165 166 167
/* Status code for GOAWAY, introduced in SPDY/3 */
typedef enum {
  SPDYLAY_GOAWAY_OK = 0,
  SPDYLAY_GOAWAY_PROTOCOL_ERROR = 1,
  SPDYLAY_GOAWAY_INTERNAL_ERROR = 11
} spdylay_goaway_status_code;

168 169
#define SPDYLAY_SPDY2_PRI_LOWEST 3
#define SPDYLAY_SPDY3_PRI_LOWEST 7
170

171 172 173 174 175 176 177 178 179 180 181
typedef struct {
  uint16_t version;
  uint16_t type;
  uint8_t flags;
  int32_t length;
} spdylay_ctrl_hd;

typedef struct {
  spdylay_ctrl_hd hd;
  int32_t stream_id;
  int32_t assoc_stream_id;
182 183
  /* 0 (Highest) to SPDYLAY_SPDY2_PRI_LOWEST or
     SPDYLAY_SPDY3_PRI_LOWEST (loweset), depending on the protocol
184
     version. */
185
  uint8_t pri;
186
  /* Since SPDY/3 */
187
  uint8_t slot;
188 189 190 191 192 193 194 195 196
  char **nv;
} spdylay_syn_stream;

typedef struct {
  spdylay_ctrl_hd hd;
  int32_t stream_id;
  char **nv;
} spdylay_syn_reply;

197 198 199 200 201 202
typedef struct {
  spdylay_ctrl_hd hd;
  int32_t stream_id;
  char **nv;
} spdylay_headers;

203 204 205 206 207 208
typedef struct {
  spdylay_ctrl_hd hd;
  int32_t stream_id;
  uint32_t status_code;
} spdylay_rst_stream;

209 210 211 212 213 214 215 216 217 218 219 220 221
typedef struct {
  int32_t settings_id;
  uint8_t flags;
  uint32_t value;
} spdylay_settings_entry;

typedef struct {
  spdylay_ctrl_hd hd;
  /* Number of entries in |iv| */
  size_t niv;
  spdylay_settings_entry *iv;
} spdylay_settings;

222 223 224 225 226
typedef struct {
  spdylay_ctrl_hd hd;
  uint32_t unique_id;
} spdylay_ping;

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
227 228 229
typedef struct {
  spdylay_ctrl_hd hd;
  int32_t last_good_stream_id;
230
  /* Since SPDY/3 */
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
231 232 233
  uint32_t status_code;
} spdylay_goaway;

234 235 236 237 238 239 240
/* WINDOW_UPDATE is introduced since SPDY/3 */
typedef struct {
  spdylay_ctrl_hd hd;
  int32_t stream_id;
  int32_t delta_window_size;
} spdylay_window_update;

241 242 243 244 245
typedef union {
  int fd;
  void *ptr;
} spdylay_data_source;

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
246 247
/*
 * Callback function invoked when the library wants to read data from
248 249 250 251 252 253 254 255 256 257 258 259
 * |source|. The read data is sent in the stream |stream_id|. The
 * implementation of this function must read at most |length| bytes of
 * data from |source| (or possibly other places) and store them in
 * |buf| and return number of data stored in |buf|. If EOF is reached,
 * set |*eof| to 1.  If the application wants to postpone DATA frames,
 * (e.g., asynchronous I/O, or reading data blocks for long time), it
 * is achieved by returning SPDYLAY_ERR_DEFERRED without reading any
 * data in this invocation.  The library removes DATA frame from
 * outgoing queue temporarily.  To move back deferred DATA frame to
 * outgoing queue, call spdylay_session_resume_data().  In case of
 * error, return SPDYLAY_ERR_CALLBACK_FAILURE, which leads to session
 * failure.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
260
 */
261
typedef ssize_t (*spdylay_data_source_read_callback)
262 263
(spdylay_session *session, int32_t stream_id,
 uint8_t *buf, size_t length, int *eof,
264 265 266 267 268 269 270 271 272 273
 spdylay_data_source *source, void *user_data);

typedef struct {
  spdylay_data_source source;
  spdylay_data_source_read_callback read_callback;
} spdylay_data_provider;

typedef struct {
  int32_t stream_id;
  uint8_t flags;
274 275
  /* Initially eof is 0. It becomes 1 if all data are read. */
  uint8_t eof;
276 277 278
  spdylay_data_provider data_prd;
} spdylay_data;

279 280 281 282
typedef union {
  spdylay_syn_stream syn_stream;
  spdylay_syn_reply syn_reply;
  spdylay_rst_stream rst_stream;
283
  spdylay_settings settings;
284
  spdylay_ping ping;
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
285
  spdylay_goaway goaway;
286
  spdylay_headers headers;
287 288
  /* Since SPDY/3 */
  spdylay_window_update window_update;
289
  spdylay_data data;
290 291
} spdylay_frame;

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
292 293 294 295 296 297 298 299
/*
 * Callback function invoked when |session| want to send data to
 * remote peer. The implementation of this function must send at most
 * |length| bytes of data stored in |data|. It must return the number
 * of bytes sent if it succeeds.  If it cannot send any single byte
 * without blocking, it must return SPDYLAY_ERR_WOULDBLOCK. For other
 * errors, it must return SPDYLAY_ERR_CALLBACK_FAILURE.
 */
300
typedef ssize_t (*spdylay_send_callback)
301 302
(spdylay_session *session,
 const uint8_t *data, size_t length, int flags, void *user_data);
303

304
/*
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
305
 * Callback function invoked when |session| want to receive data from
306 307
 * remote peer. The implementation of this function must read at most
 * |length| bytes of data and store it in |buf|. It must return the
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
308 309 310 311 312
 * number of bytes written in |buf| if it succeeds. If it cannot read
 * any single byte without blocking, it must return
 * SPDYLAY_ERR_WOULDBLOCK. If it gets EOF before it reads any single
 * byte, it must return SPDYLAY_ERR_EOF. For other errors, it must
 * return SPDYLAY_ERR_CALLBACK_FAILURE.
313
 */
314
typedef ssize_t (*spdylay_recv_callback)
315 316
(spdylay_session *session,
 uint8_t *buf, size_t length, int flags, void *user_data);
317

318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
/*
 * Callback function invoked by spdylay_session_recv() when a control
 * frame is arrived.
 */
typedef void (*spdylay_on_ctrl_recv_callback)
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
 void *user_data);

/*
 * Callback function invoked by spdylay_session_recv() when an invalid
 * control frame is arrived, which typically the case where RST_STREAM
 * will be sent
 */
typedef void (*spdylay_on_invalid_ctrl_recv_callback)
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
 void *user_data);

335 336 337 338
/*
 * Callback function invoked when data chunk of DATA frame is
 * received. |stream_id| is the stream ID of this DATA frame belongs
 * to. |flags| is the flags of DATA frame which this data chunk is
339 340 341
 * contained. flags & SPDYLAY_DATA_FLAG_FIN does not necessarily mean
 * this chunk of data is the last one in the stream. You should use
 * spdylay_on_data_recv_callback to know all data frames are received.
342 343
 */
typedef void (*spdylay_on_data_chunk_recv_callback)
344
(spdylay_session *session, uint8_t flags, int32_t stream_id,
345 346 347 348 349 350 351
 const uint8_t *data, size_t len, void *user_data);

/*
 * Callback function invoked when DATA frame is received. The actual
 * data it contains are received by spdylay_on_data_recv_callback.
 */
typedef void (*spdylay_on_data_recv_callback)
352
(spdylay_session *session, uint8_t flags, int32_t stream_id, int32_t length,
353 354
 void *user_data);

355 356 357 358 359 360 361 362
/*
 * Callback function invoked after frame |frame| of type |type| is
 * sent.
 */
typedef void (*spdylay_on_ctrl_send_callback)
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
 void *user_data);

363 364 365 366 367 368 369 370 371
/*
 * Callback function invoked after the control frame |frame| of type
 * |type| is not sent because of the error. The error is indicated by
 * the |error|, which is one of the values defined in spdylay_error.
 */
typedef void (*spdylay_on_ctrl_not_send_callback)
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
 int error, void *user_data);

372 373 374 375 376 377 378
/*
 * Callback function invoked after DATA frame is sent.
 */
typedef void (*spdylay_on_data_send_callback)
(spdylay_session *session, uint8_t flags, int32_t stream_id, int32_t length,
 void *user_data);

379 380 381
/*
 * Callback function invoked before frame |frame| of type |type| is
 * sent. This may be useful, for example, to know the stream ID of
382 383
 * SYN_STREAM frame (see also spdylay_session_get_stream_user_data),
 * which is not assigned when it was queued.
384 385 386 387 388
 */
typedef void (*spdylay_before_ctrl_send_callback)
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
 void *user_data);

389 390
/*
 * Callback function invoked when stream |stream_id| is closed. The
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
391 392
 * reason of closure is indicated by |status_code|. stream_user_data
 * is still available in this function.
393 394 395 396 397
 */
typedef void (*spdylay_on_stream_close_callback)
(spdylay_session *session, int32_t stream_id, spdylay_status_code status_code,
 void *user_data);

398 399 400 401 402 403 404 405 406
/*
 * Callback function invoked when request from remote peer is
 * received.  In other words, frame with FIN flag set is received.  In
 * HTTP, this means HTTP request, including request body, is fully
 * received.
 */
typedef void (*spdylay_on_request_recv_callback)
(spdylay_session *session, int32_t stream_id, void *user_data);

407 408 409
typedef struct {
  spdylay_send_callback send_callback;
  spdylay_recv_callback recv_callback;
410 411
  spdylay_on_ctrl_recv_callback on_ctrl_recv_callback;
  spdylay_on_invalid_ctrl_recv_callback on_invalid_ctrl_recv_callback;
412 413
  spdylay_on_data_chunk_recv_callback on_data_chunk_recv_callback;
  spdylay_on_data_recv_callback on_data_recv_callback;
414
  spdylay_before_ctrl_send_callback before_ctrl_send_callback;
415
  spdylay_on_ctrl_send_callback on_ctrl_send_callback;
416
  spdylay_on_ctrl_not_send_callback on_ctrl_not_send_callback;
417
  spdylay_on_data_send_callback on_data_send_callback;
418
  spdylay_on_stream_close_callback on_stream_close_callback;
419
  spdylay_on_request_recv_callback on_request_recv_callback;
420 421
} spdylay_session_callbacks;

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
422
/*
423 424 425 426 427
 * Initializes |*session_ptr| for client use, using the protocol
 * version |version|. The all members of |callbacks| are copied to
 * |*session_ptr|. Therefore |*session_ptr| does not store
 * |callbacks|. |user_data| is an arbitrary user supplied data, which
 * will be passed to the callback functions.
428 429 430 431 432 433
 *
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
434 435 436 437
 * SPDYLAY_ERR_ZLIB
 *     The z_stream initialization failed.
 * SPDYLAY_ERR_UNSUPPORTED_VERSION
 *     The version is not supported.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
438
 */
439
int spdylay_session_client_new(spdylay_session **session_ptr,
440
                               uint16_t version,
441
                               const spdylay_session_callbacks *callbacks,
442 443 444
                               void *user_data);

/*
445 446 447 448 449
 * Initializes |*session_ptr| for server use, using the protocol
 * version |version|. The all members of |callbacks| are copied to
 * |*session_ptr|. Therefore |*session_ptr| does not store
 * |callbacks|. |user_data| is an arbitrary user supplied data, which
 * will be passed to the callback functions.
450 451 452 453 454 455
 *
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
456 457 458 459
 * SPDYLAY_ERR_ZLIB
 *     The z_stream initialization failed.
 * SPDYLAY_ERR_UNSUPPORTED_VERSION
 *     The version is not supported.
460 461
 */
int spdylay_session_server_new(spdylay_session **session_ptr,
462
                               uint16_t version,
463
                               const spdylay_session_callbacks *callbacks,
464
                               void *user_data);
465

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
466 467 468
/*
 * Frees any resources allocated for |session|.
 */
469
void spdylay_session_del(spdylay_session *session);
470

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
471
/*
472 473
 * Sends pending frames to the remote peer.
 *
474 475 476 477 478 479 480 481 482 483
 * This function retrieves the highest prioritized frame from the
 * outbound queue and sends it to the remote peer. It does this as
 * many as possible until the user callback send_callback returns
 * SPDYLAY_ERR_WOULDBLOCK or the outbound queue becomes empty.  This
 * function calls several callback functions which are passed when
 * initializing the |session|. Here is the simple time chart which
 * tells when each callback is invoked:
 *
 * 1. Get the next frame to send from outbound queue.
 * 2. Prepare transmission of the frame.
484 485 486 487 488 489
 * 3. If the control frame cannot be sent because some preconditions
 *    are not met (e.g., SYN_STREAM cannot be sent after GOAWAY),
 *    on_ctrl_not_send_callback is invoked. Skip following steps.
 * 4. If the frame is SYN_STREAM, the stream is opened here.
 * 5. before_ctrl_send_callback is invoked.
 * 6. send_callback is invoked one or more times (while the frame is
490
 *    completely sent).
491 492 493
 * 7. If the frame is a control frame, on_ctrl_send_callback is invoked.
 * 8. If the frame is a DATA frame, on_data_send_callback is invoked.
 * 9. If the transmission of the frame triggers closure of the stream,
494 495
 *    the stream is closed and on_stream_close_callback is invoked.
 *
496 497 498 499 500 501 502
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
 * SPDYLAY_ERR_CALLBACK_FAILURE
 *     The callback function failed.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
503
 */
504 505
int spdylay_session_send(spdylay_session *session);

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
506
/*
507 508
 * Receives frames from the remote peer.
 *
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
 * This function receives as many frames as possible until the user
 * callback recv_callback returns SPDYLAY_ERR_WOULDBLOCK. This
 * function calls several callback functions which are passed when
 * initializing the |session|. Here is the simple time chart which
 * tells when each callback is invoked:
 *
 * 1. recv_callback is invoked one or more times to receive frame header.
 * 2. If the frame is DATA frame:
 *   2.1. recv_callback is invoked to receive DATA payload. For each
 *        chunk of data, on_data_chunk_recv_callback is invoked.
 *   2.2. If one DATA frame is completely received, on_data_recv_callback
 *        is invoked.
 *        If the frame is the final frame of the request,
 *        on_request_recv_callback is invoked.
 *        If the reception of the frame triggers the closure of the stream,
 *        on_stream_close_callback is invoked.
 * 3. If the frame is the control frame:
 *   3.1. recv_callback is invoked one or more times to receive whole frame.
 *   3.2. If the received frame is valid, on_ctrl_recv_callback is invoked.
 *        If the frame is the final frame of the request,
 *        on_request_recv_callback is invoked.
 *        If the reception of the frame triggers the closure of the stream,
 *        on_stream_close_callback is invoked.
 *   3.3. If the received frame is unpacked but is interpreted as invalid,
 *        on_invalid_ctrl_recv_callback is invoked.
 *
535 536 537 538 539 540 541 542 543
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_EOF
 *     The remote peer did shutdown on the connection.
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
 * SPDYLAY_ERR_CALLBACK_FAILURE
 *     The callback function failed.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
544
 */
545 546
int spdylay_session_recv(spdylay_session *session);

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
547 548 549 550 551 552 553 554 555 556 557 558 559 560
/*
 * Put back previously deferred DATA frame in the stream |stream_id|
 * to outbound queue.
 *
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_INVALID_ARGUMENT
 *     The stream does not exist or no deferred data exist.
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
 */
int spdylay_session_resume_data(spdylay_session *session, int32_t stream_id);

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
561
/*
562 563
 * Returns nonzero value if |session| want to receive data from the
 * remote peer.
564
 *
565
 * If both spdylay_session_want_read() and
566 567
 * spdylay_session_want_write() return 0, the application should drop
 * the connection.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
568
 */
569 570
int spdylay_session_want_read(spdylay_session *session);

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
571
/*
572
 * Returns nonzero value if |session| want to send data to the remote
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
573
 * peer, or 0.
574
 *
575
 * If both spdylay_session_want_read() and
576 577
 * spdylay_session_want_write() return 0, the application should drop
 * the connection.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
578
 */
579 580
int spdylay_session_want_write(spdylay_session *session);

581 582 583 584 585 586 587 588 589 590 591 592
/*
 * Returns stream_user_data for the stream |stream_id|. The
 * stream_user_data is provided by spdylay_submit_request().  If the
 * stream is initiated by the remote endpoint, stream_user_data is
 * always NULL. If the stream is initiated by the local endpoint and
 * NULL is given in spdylay_submit_request(), then this function
 * returns NULL. If the stream does not exist, this function returns
 * NULL.
 */
void* spdylay_session_get_stream_user_data(spdylay_session *session,
                                           int32_t stream_id);

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
593
/*
594
 * Submits SYN_STREAM frame and optionally one or more DATA
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
595
 * frames.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
596
 *
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
597 598 599 600
 * |pri| is priority of this request. 0 is the highest priority.  If
 * the |session| is initialized with the version SPDYLAY_PROTO_SPDY2,
 * the lowest priority is 3.  If the |session| is initialized with the
 * version SPDYLAY_PROTO_SPDY3, the lowest priority is 7.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
601
 *
602
 * The |nv| must include following name/value pairs:
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
603 604 605 606 607 608 609 610 611 612 613 614 615 616
 *
 * ":method"
 *     HTTP method (e.g., "GET", "POST", "HEAD", etc)
 * ":scheme"
 *     URI scheme (e.g., "https")
 * ":path"
 *     Absolute path and parameters of this request (e.g., "/foo",
 *     "/foo;bar;haz?h=j&y=123")
 * ":version"
 *     HTTP version (e.g., "HTTP/1.1")
 * ":host"
 *     The hostport portion of the URI for this request (e.g.,
 *     "example.org:443"). This is the same as the HTTP "Host" header
 *     field.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
617
 *
618 619 620 621
 * If the |session| is initialized with the version
 * SPDYLAY_PROTO_SPDY2, the above names are translated to "method",
 * "scheme", "url", "version" and "host" respectively.
 *
622 623
 * This function creates copies of all name/value pairs in |nv|.  It
 * also lower-cases all names in |nv|.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
624
 *
625
 * If |data_prd| is not NULL, it provides data which will be sent in
626
 * subsequent DATA frames. In this case, a method that allows request
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
627 628 629
 * message bodies
 * (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9) must
 * be specified with "method" key in |nv| (e.g. POST). If |data_prd|
630 631
 * is NULL, SYN_STREAM have FLAG_FIN. The |stream_user_data| is data
 * associated to the stream opened by this request and can be an
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
632
 * arbitrary pointer, which can be retrieved by
633 634 635 636 637 638 639 640 641 642 643 644
 * spdylay_session_get_stream_user_data().
 *
 * Since the library reorders the frames and tries to send the highest
 * prioritized one first and the SPDY specification requires the
 * stream ID must be strictly increasing, the stream ID of this
 * request cannot be known until it is about to sent.  To know the
 * stream ID of the request, the application can use
 * before_ctrl_send_callback. This callback is called just before the
 * frame is sent. For SYN_STREAM frame, the argument frame has stream
 * ID assigned. Also since the stream is already opened,
 * spdylay_session_get_stream_user_data() can be used to get
 * |stream_user_data| to identify which SYN_STREAM we are processing.
645
 *
646 647 648 649 650 651 652
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_INVALID_FRAME
 *     |pri| is invalid.
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
653
 */
654
int spdylay_submit_request(spdylay_session *session, uint8_t pri,
655
                           const char **nv,
656
                           const spdylay_data_provider *data_prd,
657
                           void *stream_user_data);
658

659
/*
660
 * Submits SYN_REPLY frame and optionally one or more DATA frames
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
661 662
 * against stream |stream_id|.
 *
663
 * The |nv| must include following name/value pairs:
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
664
 *
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
665 666 667 668
 * ":status"
 *     HTTP status code (e.g., "200" or "200 OK")
 * ":version"
 *     HTTP response version (e.g., "HTTP/1.1")
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
669
 *
670 671 672 673
 * If the |session| is initialized with the version
 * SPDYLAY_PROTO_SPDY2, the above names are translated to "status" and
 * "version" respectively.
 *
674 675 676 677
 * This function creates copies of all name/value pairs in |nv|.  It
 * also lower-cases all names in |nv|.
 *
 * If |data_prd| is not NULL, it provides data which will be sent in
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
678 679 680
 * subsequent DATA frames. If |data_prd| is NULL, SYN_REPLY will have
 * FLAG_FIN.
 *
681 682 683 684 685
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
686
 */
687 688
int spdylay_submit_response(spdylay_session *session,
                            int32_t stream_id, const char **nv,
689
                            const spdylay_data_provider *data_prd);
690

691 692 693 694
/*
 * Submits SYN_STREAM frame. The |flags| is bitwise OR of the
 * following values:
 *
695 696
 * SPDYLAY_CTRL_FLAG_FIN
 * SPDYLAY_CTRL_FLAG_UNIDIRECTIONAL
697
 *
698 699
 * If |flags| includes SPDYLAY_CTRL_FLAG_FIN, this frame has FIN flag
 * set.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
700
 *
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
 * The |assoc_stream_id| is used for server-push. If |session| is
 * initialized for client use, |assoc_stream_id| is ignored. The |pri|
 * is the priority of this frame and it must be between 0 and 3,
 * inclusive. 0 is the highest. The |nv| is the name/value pairs in
 * this frame. The |stream_user_data| is a pointer to an arbitrary
 * data which is associated to the stream this frame will open.
 *
 * This function is low-level in a sense that the application code can
 * specify flags and assoc-stream-ID directly. For usual HTTP request,
 * spdylay_submit_request() is useful.
 *
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_INVALID_FRAME
 *     |pri| is invalid.
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
 */
int spdylay_submit_syn_stream(spdylay_session *session, uint8_t flags,
721
                              int32_t assoc_stream_id, uint8_t pri,
722 723
                              const char **nv, void *stream_user_data);

724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
/*
 * Submits SYN_REPLY frame. The |flags| is bitwise OR of the following
 * values:
 *
 * SPDYLAY_CTRL_FLAG_FIN
 *
 * If |flags| includes SPDYLAY_CTRL_FLAG_FIN, this frame has FIN flag
 * set.
 *
 * The stream this frame belongs to is given in |stream_id|. The |nv|
 * is the name/value pairs in this frame.
 *
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
 */
int spdylay_submit_syn_reply(spdylay_session *session, uint8_t flags,
                             int32_t stream_id, const char **nv);

745 746 747 748
/*
 * Submits HEADERS frame. The |flags| is bitwise OR of the following
 * values:
 *
749
 * SPDYLAY_CTRL_FLAG_FIN
750
 *
751 752
 * If |flags| includes SPDYLAY_CTRL_FLAG_FIN, this frame has FIN flag
 * set.
753 754 755 756 757 758 759 760 761 762 763 764 765
 *
 * The stream this frame belongs to is given in |stream_id|. The |nv|
 * is the name/value pairs in this frame.
 *
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
 */
int spdylay_submit_headers(spdylay_session *session, uint8_t flags,
                           int32_t stream_id, const char **nv);

766 767 768 769
/*
 * Submits 1 or more DATA frames to the stream |stream_id|.  The data
 * to be sent are provided by |data_prd|.  Depending on the length of
 * data, 1 or more DATA frames will be sent.  If |flags| contains
770
 * SPDYLAY_DATA_FLAG_FIN, the last DATA frame has FLAG_FIN set.
771
 *
772 773 774 775 776
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
777 778
 */
int spdylay_submit_data(spdylay_session *session, int32_t stream_id,
779
                        uint8_t flags, const spdylay_data_provider *data_prd);
780

781
/*
782
 * Submits RST_STREAM frame to cancel/reject stream |stream_id| with
783 784 785 786 787 788 789
 * status code |status_code|.
 *
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
790
 */
791 792
int spdylay_submit_rst_stream(spdylay_session *session, int32_t stream_id,
                              uint32_t status_code);
793

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
794
/*
795 796 797 798 799 800 801
 * Submits PING frame.
 *
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
802
 */
803 804
int spdylay_submit_ping(spdylay_session *session);

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
805
/*
806 807
 * Submits GOAWAY frame. The status code |status_code| is ignored if
 * the protocol version is SPDYLAY_PROTO_SPDY2.
808 809 810 811 812 813
 *
 * This function returns 0 if it succeeds, or one of the following
 * negative error codes:
 *
 * SPDYLAY_ERR_NOMEM
 *     Out of memory.
Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
814
 */
815
int spdylay_submit_goaway(spdylay_session *session, uint32_t status_code);
816

817
/*
818 819 820 821 822 823 824 825 826 827 828 829 830
 * A helper function for dealing with NPN in client side.
 * |in| contains server's protocol in preferable order.
 * The format of |in| is length-prefixed and not null-terminated.
 * For example, "spdy/2" are "http/1.1" stored in |in| like this:
 *
 *  in[0] = 6
 *  in[1..6] = "spdy/2"
 *  in[7] = 8
 *  in[8..15] = "http/1.1"
 *  inlen = 16
 *
 * The selection algorithm is as follows:
 *
831 832 833 834 835
 * 1. If server's list contains SPDY versions the spdylay library
 *    supports, this function selects one of them and returns its SPDY
 *    protocol version which can be used directly with
 *    spdylay_session_client_new() and spdylay_session_server_new()
 *    . The following steps are not taken.
836 837 838 839
 *
 * 2. If server's list contains "http/1.1", this function selects
 *    "http/1.1" and returns 0. The following step is not taken.
 *
840 841 842
 * 3. This function selects nothing and returns -1. (So called
 *    non-overlap case). In this case, |out| and |outlen| are left
 *    untouched.
843 844 845 846 847
 *
 * When spdylay supports updated version of SPDY in the future, this
 * function may select updated protocol and application code which
 * relies on spdylay for SPDY stuff needs not be modified.
 *
848 849 850
 * Selecting "spdy/2" means that "spdy/2" is written into |*out| and
 * length of "spdy/2" (which is 6) is assigned to |*outlen|.
 *
851 852 853
 * See http://technotes.googlecode.com/git/nextprotoneg.html for more
 * details about NPN.
 *
854
 * To use this method you should do something like:
855
 *
856 857 858 859 860
 * static int select_next_proto_cb(SSL* ssl,
 *                                 unsigned char **out, unsigned char *outlen,
 *                                 const unsigned char *in, unsigned int inlen,
 *                                 void *arg)
 * {
861 862 863 864
 *   int version;
 *   version = spdylay_select_next_protocol(out, outlen, in, inlen);
 *   if(version > 0) {
 *     ((MyType*)arg)->spdy_version = version;
865 866 867 868 869 870 871 872 873
 *   }
 *   return SSL_TLSEXT_ERR_OK;
 * }
 * ...
 * SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, my_obj);
 */
int spdylay_select_next_protocol(unsigned char **out, unsigned char *outlen,
                                 const unsigned char *in, unsigned int inlen);

874 875 876 877 878 879 880 881 882 883
/*
 * Returns spdy version which spdylay library supports from given
 * protocol name. The |proto| is the pointer to the protocol name and
 * |protolen| is its length. Currently, "spdy/2" and "spdy/3" are
 * supported.
 *
 * This function returns nonzero spdy version if it succeeds, or 0.
 */
uint16_t spdylay_npn_get_version(const unsigned char *proto, size_t protolen);

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
884 885 886 887
#ifdef __cplusplus
}
#endif

Tatsuhiro Tsujikawa's avatar
Tatsuhiro Tsujikawa committed
888
#endif /* SPDYLAY_H */