1/*
2 * nghttp3
3 *
4 * Copyright (c) 2019 nghttp3 contributors
5 * Copyright (c) 2013 nghttp2 contributors
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26#ifndef NGHTTP3_FRAME_H
27#define NGHTTP3_FRAME_H
28
29#ifdef HAVE_CONFIG_H
30#  include <config.h>
31#endif /* HAVE_CONFIG_H */
32
33#include <nghttp3/nghttp3.h>
34
35#include "nghttp3_buf.h"
36
37typedef enum nghttp3_frame_type {
38  NGHTTP3_FRAME_DATA = 0x00,
39  NGHTTP3_FRAME_HEADERS = 0x01,
40  NGHTTP3_FRAME_CANCEL_PUSH = 0x03,
41  NGHTTP3_FRAME_SETTINGS = 0x04,
42  NGHTTP3_FRAME_PUSH_PROMISE = 0x05,
43  NGHTTP3_FRAME_GOAWAY = 0x07,
44  NGHTTP3_FRAME_MAX_PUSH_ID = 0x0d,
45  /* PRIORITY_UPDATE:
46     https://tools.ietf.org/html/draft-ietf-httpbis-priority-03 */
47  NGHTTP3_FRAME_PRIORITY_UPDATE = 0x0f0700,
48  NGHTTP3_FRAME_PRIORITY_UPDATE_PUSH_ID = 0x0f0701,
49} nghttp3_frame_type;
50
51typedef enum nghttp3_h2_reserved_type {
52  NGHTTP3_H2_FRAME_PRIORITY = 0x02,
53  NGHTTP3_H2_FRAME_PING = 0x06,
54  NGHTTP3_H2_FRAME_WINDOW_UPDATE = 0x08,
55  NGHTTP3_H2_FRAME_CONTINUATION = 0x9,
56} nghttp3_h2_reserved_type;
57
58typedef struct nghttp3_frame_hd {
59  int64_t type;
60  int64_t length;
61} nghttp3_frame_hd;
62
63typedef struct nghttp3_frame_data {
64  nghttp3_frame_hd hd;
65} nghttp3_frame_data;
66
67typedef struct nghttp3_frame_headers {
68  nghttp3_frame_hd hd;
69  nghttp3_nv *nva;
70  size_t nvlen;
71} nghttp3_frame_headers;
72
73#define NGHTTP3_SETTINGS_ID_MAX_FIELD_SECTION_SIZE 0x06
74#define NGHTTP3_SETTINGS_ID_QPACK_MAX_TABLE_CAPACITY 0x01
75#define NGHTTP3_SETTINGS_ID_QPACK_BLOCKED_STREAMS 0x07
76#define NGHTTP3_SETTINGS_ID_ENABLE_CONNECT_PROTOCOL 0x08
77
78#define NGHTTP3_H2_SETTINGS_ID_ENABLE_PUSH 0x2
79#define NGHTTP3_H2_SETTINGS_ID_MAX_CONCURRENT_STREAMS 0x3
80#define NGHTTP3_H2_SETTINGS_ID_INITIAL_WINDOW_SIZE 0x4
81#define NGHTTP3_H2_SETTINGS_ID_MAX_FRAME_SIZE 0x5
82
83typedef struct nghttp3_settings_entry {
84  uint64_t id;
85  uint64_t value;
86} nghttp3_settings_entry;
87
88typedef struct nghttp3_frame_settings {
89  nghttp3_frame_hd hd;
90  size_t niv;
91  nghttp3_settings_entry iv[1];
92} nghttp3_frame_settings;
93
94typedef struct nghttp3_frame_goaway {
95  nghttp3_frame_hd hd;
96  int64_t id;
97} nghttp3_frame_goaway;
98
99typedef struct nghttp3_frame_priority_update {
100  nghttp3_frame_hd hd;
101  /* pri_elem_id is stream ID if hd.type ==
102     NGHTTP3_FRAME_PRIORITY_UPDATE.  It is push ID if hd.type ==
103     NGHTTP3_FRAME_PRIORITY_UPDATE_PUSH_ID.  It is undefined
104     otherwise. */
105  int64_t pri_elem_id;
106  nghttp3_pri pri;
107} nghttp3_frame_priority_update;
108
109typedef union nghttp3_frame {
110  nghttp3_frame_hd hd;
111  nghttp3_frame_data data;
112  nghttp3_frame_headers headers;
113  nghttp3_frame_settings settings;
114  nghttp3_frame_goaway goaway;
115  nghttp3_frame_priority_update priority_update;
116} nghttp3_frame;
117
118/*
119 * nghttp3_frame_write_hd writes frame header |hd| to |dest|.  This
120 * function assumes that |dest| has enough space to write |hd|.
121 *
122 * This function returns |dest| plus the number of bytes written.
123 */
124uint8_t *nghttp3_frame_write_hd(uint8_t *dest, const nghttp3_frame_hd *hd);
125
126/*
127 * nghttp3_frame_write_hd_len returns the number of bytes required to
128 * write |hd|.  hd->length must be set.
129 */
130size_t nghttp3_frame_write_hd_len(const nghttp3_frame_hd *hd);
131
132/*
133 * nghttp3_frame_write_settings writes SETTINGS frame |fr| to |dest|.
134 * This function assumes that |dest| has enough space to write |fr|.
135 *
136 * This function returns |dest| plus the number of bytes written.
137 */
138uint8_t *nghttp3_frame_write_settings(uint8_t *dest,
139                                      const nghttp3_frame_settings *fr);
140
141/*
142 * nghttp3_frame_write_settings_len returns the number of bytes
143 * required to write |fr|.  fr->hd.length is ignored.  This function
144 * stores payload length in |*ppayloadlen|.
145 */
146size_t nghttp3_frame_write_settings_len(int64_t *pppayloadlen,
147                                        const nghttp3_frame_settings *fr);
148
149/*
150 * nghttp3_frame_write_goaway writes GOAWAY frame |fr| to |dest|.
151 * This function assumes that |dest| has enough space to write |fr|.
152 *
153 * This function returns |dest| plus the number of bytes written.
154 */
155uint8_t *nghttp3_frame_write_goaway(uint8_t *dest,
156                                    const nghttp3_frame_goaway *fr);
157
158/*
159 * nghttp3_frame_write_goaway_len returns the number of bytes required
160 * to write |fr|.  fr->hd.length is ignored.  This function stores
161 * payload length in |*ppayloadlen|.
162 */
163size_t nghttp3_frame_write_goaway_len(int64_t *ppayloadlen,
164                                      const nghttp3_frame_goaway *fr);
165
166/*
167 * nghttp3_frame_write_priority_update writes PRIORITY_UPDATE frame
168 * |fr| to |dest|.  This function assumes that |dest| has enough space
169 * to write |fr|.
170 *
171 * This function returns |dest| plus the number of bytes written;
172 */
173uint8_t *
174nghttp3_frame_write_priority_update(uint8_t *dest,
175                                    const nghttp3_frame_priority_update *fr);
176
177/*
178 * nghttp3_frame_write_priority_update_len returns the number of bytes
179 * required to write |fr|.  fr->hd.length is ignored.  This function
180 * stores payload length in |*ppayloadlen|.
181 */
182size_t nghttp3_frame_write_priority_update_len(
183    int64_t *ppayloadlen, const nghttp3_frame_priority_update *fr);
184
185/*
186 * nghttp3_nva_copy copies name/value pairs from |nva|, which contains
187 * |nvlen| pairs, to |*nva_ptr|, which is dynamically allocated so
188 * that all items can be stored.  The resultant name and value in
189 * nghttp2_nv are guaranteed to be NULL-terminated even if the input
190 * is not null-terminated.
191 *
192 * The |*pnva| must be freed using nghttp3_nva_del().
193 *
194 * This function returns 0 if it succeeds or one of the following
195 * negative error codes:
196 *
197 * NGHTTP3_ERR_NOMEM
198 *     Out of memory.
199 */
200int nghttp3_nva_copy(nghttp3_nv **pnva, const nghttp3_nv *nva, size_t nvlen,
201                     const nghttp3_mem *mem);
202
203/*
204 * nghttp3_nva_del frees |nva|.
205 */
206void nghttp3_nva_del(nghttp3_nv *nva, const nghttp3_mem *mem);
207
208/*
209 * nghttp3_frame_headers_free frees memory allocated for |fr|.  It
210 * assumes that fr->nva is created by nghttp3_nva_copy() or NULL.
211 */
212void nghttp3_frame_headers_free(nghttp3_frame_headers *fr,
213                                const nghttp3_mem *mem);
214
215#endif /* NGHTTP3_FRAME_H */
216