1 /*
2  * ngtcp2
3  *
4  * Copyright (c) 2017 ngtcp2 contributors
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 #ifndef NGTCP2_STRM_H
26 #define NGTCP2_STRM_H
27 
28 #ifdef HAVE_CONFIG_H
29 #  include <config.h>
30 #endif /* HAVE_CONFIG_H */
31 
32 #include <ngtcp2/ngtcp2.h>
33 
34 #include "ngtcp2_rob.h"
35 #include "ngtcp2_map.h"
36 #include "ngtcp2_gaptr.h"
37 #include "ngtcp2_ksl.h"
38 #include "ngtcp2_pq.h"
39 
40 typedef struct ngtcp2_frame_chain ngtcp2_frame_chain;
41 
42 /* NGTCP2_STRM_FLAG_NONE indicates that no flag is set. */
43 #define NGTCP2_STRM_FLAG_NONE 0x00
44 /* NGTCP2_STRM_FLAG_SHUT_RD indicates that further reception of stream
45    data is not allowed. */
46 #define NGTCP2_STRM_FLAG_SHUT_RD 0x01
47 /* NGTCP2_STRM_FLAG_SHUT_WR indicates that further transmission of
48    stream data is not allowed. */
49 #define NGTCP2_STRM_FLAG_SHUT_WR 0x02
50 #define NGTCP2_STRM_FLAG_SHUT_RDWR                                             \
51   (NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_SHUT_WR)
52 /* NGTCP2_STRM_FLAG_SENT_RST indicates that RST_STREAM is sent from
53    the local endpoint.  In this case, NGTCP2_STRM_FLAG_SHUT_WR is also
54    set. */
55 #define NGTCP2_STRM_FLAG_SENT_RST 0x04
56 /* NGTCP2_STRM_FLAG_SENT_RST indicates that RST_STREAM is received
57    from the remote endpoint.  In this case, NGTCP2_STRM_FLAG_SHUT_RD
58    is also set. */
59 #define NGTCP2_STRM_FLAG_RECV_RST 0x08
60 /* NGTCP2_STRM_FLAG_STOP_SENDING indicates that STOP_SENDING is sent
61    from the local endpoint. */
62 #define NGTCP2_STRM_FLAG_STOP_SENDING 0x10
63 /* NGTCP2_STRM_FLAG_RST_ACKED indicates that the outgoing RST_STREAM
64    is acknowledged by peer. */
65 #define NGTCP2_STRM_FLAG_RST_ACKED 0x20
66 /* NGTCP2_STRM_FLAG_FIN_ACKED indicates that a STREAM with FIN bit set
67    is acknowledged by a remote endpoint. */
68 #define NGTCP2_STRM_FLAG_FIN_ACKED 0x40
69 /* NGTCP2_STRM_FLAG_ANY_ACKED indicates that any portion of stream
70    data, including 0 length segment, is acknowledged. */
71 #define NGTCP2_STRM_FLAG_ANY_ACKED 0x80
72 /* NGTCP2_STRM_FLAG_APP_ERROR_CODE_SET indicates that app_error_code
73    field is set.  This resolves the ambiguity that the initial
74    app_error_code value 0 might be a proper application error code.
75    In this case, without this flag, we are unable to distinguish
76    assigned value from unassigned one.  */
77 #define NGTCP2_STRM_FLAG_APP_ERROR_CODE_SET 0x100
78 
79 typedef struct ngtcp2_strm ngtcp2_strm;
80 
81 struct ngtcp2_strm {
82   ngtcp2_pq_entry pe;
83   uint64_t cycle;
84 
85   struct {
86     /* acked_offset tracks acknowledged outgoing data. */
87     ngtcp2_gaptr *acked_offset;
88     /* cont_acked_offset is the offset that all data up to this offset
89        is acknowledged by a remote endpoint.  It is used until the
90        remote endpoint acknowledges data in out-of-order.  After that,
91        acked_offset is used instead. */
92     uint64_t cont_acked_offset;
93     /* streamfrq contains STREAM frame for retransmission.  The flow
94        control credits have been paid when they are transmitted first
95        time.  There are no restriction regarding flow control for
96        retransmission. */
97     ngtcp2_ksl *streamfrq;
98     /* offset is the next offset of outgoing data.  In other words, it
99        is the number of bytes sent in this stream without
100        duplication. */
101     uint64_t offset;
102     /* max_tx_offset is the maximum offset that local endpoint can
103        send for this stream. */
104     uint64_t max_offset;
105     /* last_max_stream_data_ts is the timestamp when last
106        MAX_STREAM_DATA frame is sent. */
107     ngtcp2_tstamp last_max_stream_data_ts;
108   } tx;
109 
110   struct {
111     /* rob is the reorder buffer for incoming stream data.  The data
112        received in out of order is buffered and sorted by its offset
113        in this object. */
114     ngtcp2_rob *rob;
115     /* cont_offset is the largest offset of consecutive data.  It is
116        used until the endpoint receives out-of-order data.  After
117        that, rob is used to track the offset and data. */
118     uint64_t cont_offset;
119     /* last_offset is the largest offset of stream data received for
120        this stream. */
121     uint64_t last_offset;
122     /* max_offset is the maximum offset that remote endpoint can send
123        to this stream. */
124     uint64_t max_offset;
125     /* unsent_max_offset is the maximum offset that remote endpoint
126        can send to this stream, and it is not notified to the remote
127        endpoint.  unsent_max_offset >= max_offset must be hold. */
128     uint64_t unsent_max_offset;
129     /* window is the stream-level flow control window size. */
130     uint64_t window;
131   } rx;
132 
133   const ngtcp2_mem *mem;
134   int64_t stream_id;
135   void *stream_user_data;
136   /* flags is bit-wise OR of zero or more of NGTCP2_STRM_FLAG_*. */
137   uint32_t flags;
138   /* app_error_code is an error code the local endpoint sent in
139      RESET_STREAM or STOP_SENDING, or received from a remote endpoint
140      in RESET_STREAM or STOP_SENDING.  First application error code is
141      chosen and when set, NGTCP2_STRM_FLAG_APP_ERROR_CODE_SET flag is
142      set in flags field. */
143   uint64_t app_error_code;
144 };
145 
146 /*
147  * ngtcp2_strm_init initializes |strm|.
148  *
149  * This function returns 0 if it succeeds, or one of the following
150  * negative error codes:
151  *
152  * NGTCP2_ERR_NOMEM
153  *     Out of memory
154  */
155 int ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags,
156                      uint64_t max_rx_offset, uint64_t max_tx_offset,
157                      void *stream_user_data, const ngtcp2_mem *mem);
158 
159 /*
160  * ngtcp2_strm_free deallocates memory allocated for |strm|.  This
161  * function does not free the memory pointed by |strm| itself.
162  */
163 void ngtcp2_strm_free(ngtcp2_strm *strm);
164 
165 /*
166  * ngtcp2_strm_rx_offset returns the minimum offset of stream data
167  * which is not received yet.
168  */
169 uint64_t ngtcp2_strm_rx_offset(ngtcp2_strm *strm);
170 
171 /*
172  * ngtcp2_strm_recv_reordering handles reordered data.
173  *
174  * It returns 0 if it succeeds, or one of the following negative error
175  * codes:
176  *
177  * NGTCP2_ERR_NOMEM
178  *     Out of memory
179  */
180 int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data,
181                                 size_t datalen, uint64_t offset);
182 
183 /*
184  * ngtcp2_strm_update_rx_offset tells that data up to offset bytes are
185  * received in order.
186  *
187  * NGTCP2_ERR_NOMEM
188  *     Out of memory
189  */
190 int ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset);
191 
192 /*
193  * ngtcp2_strm_shutdown shutdowns |strm|.  |flags| should be
194  * NGTCP2_STRM_FLAG_SHUT_RD, and/or NGTCP2_STRM_FLAG_SHUT_WR.
195  */
196 void ngtcp2_strm_shutdown(ngtcp2_strm *strm, uint32_t flags);
197 
198 /*
199  * ngtcp2_strm_streamfrq_push pushes |frc| to streamfrq for
200  * retransmission.
201  *
202  * This function returns 0 if it succeeds, or one of the following
203  * negative error codes:
204  *
205  * NGTCP2_ERR_NOMEM
206  *     Out of memory
207  */
208 int ngtcp2_strm_streamfrq_push(ngtcp2_strm *strm, ngtcp2_frame_chain *frc);
209 
210 /*
211  * ngtcp2_strm_streamfrq_pop pops the first ngtcp2_frame_chain and
212  * assigns it to |*pfrc|.  This function splits into or merges several
213  * ngtcp2_frame_chain objects so that the returned ngtcp2_frame_chain
214  * has at most |left| data length.  If there is no frames to send,
215  * this function returns 0 and |*pfrc| is NULL.
216  *
217  * This function returns 0 if it succeeds, or one of the following
218  * negative error codes:
219  *
220  * NGTCP2_ERR_NOMEM
221  *     Out of memory
222  */
223 int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
224                               size_t left);
225 
226 /*
227  * ngtcp2_strm_streamfrq_unacked_offset returns the smallest offset of
228  * unacknowledged stream data held in strm->tx.streamfrq.
229  */
230 uint64_t ngtcp2_strm_streamfrq_unacked_offset(ngtcp2_strm *strm);
231 
232 /*
233  * ngtcp2_strm_streamfrq_top returns the first ngtcp2_frame_chain.
234  * The queue must not be empty.
235  */
236 ngtcp2_frame_chain *ngtcp2_strm_streamfrq_top(ngtcp2_strm *strm);
237 
238 /*
239  * ngtcp2_strm_streamfrq_empty returns nonzero if streamfrq is empty.
240  */
241 int ngtcp2_strm_streamfrq_empty(ngtcp2_strm *strm);
242 
243 /*
244  * ngtcp2_strm_streamfrq_clear removes all frames from streamfrq.
245  */
246 void ngtcp2_strm_streamfrq_clear(ngtcp2_strm *strm);
247 
248 /*
249  * ngtcp2_strm_is_tx_queued returns nonzero if |strm| is queued.
250  */
251 int ngtcp2_strm_is_tx_queued(ngtcp2_strm *strm);
252 
253 /*
254  * ngtcp2_strm_is_all_tx_data_acked returns nonzero if all outgoing
255  * data for |strm| which have sent so far have been acknowledged.
256  */
257 int ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm *strm);
258 
259 /*
260  * ngtcp2_strm_get_unacked_range_after returns the range that is not
261  * acknowledged yet and intersects or comes after |offset|.
262  */
263 ngtcp2_range ngtcp2_strm_get_unacked_range_after(ngtcp2_strm *strm,
264                                                  uint64_t offset);
265 
266 /*
267  * ngtcp2_strm_get_acked_offset returns offset, that is the data up to
268  * this offset have been acknowledged by a remote endpoint.  It
269  * returns 0 if no data is acknowledged.
270  */
271 uint64_t ngtcp2_strm_get_acked_offset(ngtcp2_strm *strm);
272 
273 /*
274  * ngtcp2_strm_ack_data tells |strm| that the data [offset,
275  * offset+len) is acknowledged by a remote endpoint.
276  */
277 int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len);
278 
279 /*
280  * ngtcp2_strm_set_app_error_code sets |app_error_code| to |strm| and
281  * set NGTCP2_STRM_FLAG_APP_ERROR_CODE_SET flag.  If the flag is
282  * already set, this function does nothing.
283  */
284 void ngtcp2_strm_set_app_error_code(ngtcp2_strm *strm, uint64_t app_error_code);
285 
286 #endif /* NGTCP2_STRM_H */
287