1 /**
2  * Connector
3  * 
4  * Copyright:
5  * (C) 2012-2015 Tatsuhiro Tsujikawa
6  * (C) 2014-2015 Etienne Cimon
7  *
8  * License: 
9  * Distributed under the terms of the MIT license with an additional section 1.2 of the curl/libcurl project. 
10  * Consult the provided LICENSE.md file for details
11  */
12 module libhttp2.connector;
13 
14 import libhttp2.types;
15 import libhttp2.frame;
16 import libhttp2.session;
17 
18 
19 package:
20 abstract class Connector
21 {
22 public:
23 ////////////////// Protocol ////////////////////////
24 
25     /**
26      * Callback function invoked when Session wants to send data to the
27      * remote peer.  The implementation of this function must send at most
28      * |data.length| bytes of data stored in |data|.  
29      * It must return the number of bytes sent if
30      * it succeeds.  If it cannot send any single byte without blocking,
31      * it must return $(D ErrorCode.WOULDBLOCK).  For other errors,
32      * it must return $(D ErrorCode.CALLBACK_FAILURE).  
33      *
34      * This callback is required if the application uses
35      * $(D Session.send) to send data to the remote endpoint.  If
36      * the application uses solely $(D Session.memSend) instead,
37      * this callback function is unnecessary.
38      */
39     int write(in ubyte[] data);
40 	/**
41 	 * Callback function invoked when `DataFlags.NO_COPY` is
42 	 * used in `DataProvider` to send complete DATA frame.
43 	 *
44 	 * The |frame| is a DATA frame to send.  The |framehd| is the
45 	 * serialized frame header (9 bytes). The |length| is the length of
46 	 * application data to send (this does not include padding).  The
47 	 * |source| is the same pointer passed to `DataProvider`.
48 	 *
49 	 * The application first must send frame header |framehd| of length 9
50 	 * bytes.  If `frame->padlen > 0`, send 1 byte of value
51 	 * `frame->padlen - 1`.  Then send exactly |length| bytes of
52 	 * application data.  Finally, if `frame->padlen > 0`, send
53 	 * `frame->padlen - 1` bytes of zero (they are padding).
54 	 *
55 	 * The application has to send complete DATA frame in this callback.
56 	 * If all data were written successfully, return 0.
57 	 *
58 	 * If it cannot send it all, just return
59 	 * `ErrorCode.WOULDBLOCK`, the library will call this callback
60 	 * with the same parameters later (It is recommended to send complete
61 	 * DATA frame at once in this function to deal with error; if partial
62 	 * frame data has already sent, it is impossible to send another data
63 	 * in that state, and all we can do is tear down connection).  If
64 	 * application decided to reset this stream, return
65 	 * `ErrorCode.TEMPORAL_CALLBACK_FAILURE`, then the library
66 	 * will send RST_STREAM with INTERNAL_ERROR as error code.  The
67 	 * application can also return `ErrorCode.CALLBACK_FAILURE`,
68 	 * which will result in connection closure.  Returning any other value
69 	 * is treated as if `ErrorCode.CALLBACK_FAILURE` was returned.
70 	 */
71 	ErrorCode writeData(in Frame frame, ubyte[] frame_hd, uint length);
72 
73     /**
74      * Callback function invoked when Session wants to receive data from
75      * the remote peer.  The implementation of this function must read at
76      * most |data.length| bytes of data and store it in |data|.  
77      * 
78      * It must return the number of
79      * bytes written in |buf| if it succeeds.  If it cannot read any
80      * single byte without blocking, it must return
81      * $(D ErrorCode.WOULDBLOCK).  If it gets EOF before it reads any
82      * single byte, it must return $(D ErrorCode.EOF).  For other
83      * errors, it must return $(D ErrorCode.CALLBACK_FAILURE).
84      * Returning 0 is treated as $(D ErrorCode.WOULDBLOCK). 
85      *
86      * This callback is required if the application uses
87      * $(D Session.recv) to receive data from the remote endpoint.
88      * If the application uses solely `http2_session_mem_recv()`
89      * instead, this callback function is unnecessary.
90      */
91     int read(ubyte[] data);
92 
93 	/**
94      * Callback function invoked when the stream |stream_id| is closed.
95      * The reason of closure is indicated by the |error_code|.  The
96      * |error_code| is usually one of $(D FrameError), but that
97      * is not guaranteed. 
98      *
99      * This function is also called for a stream in reserved state.
100      *
101      * If this callback returns false, it is treated as fatal error and
102      * $(D Session.recv) and $(D Session.send) functions
103      * immediately return $(D ErrorCode.CALLBACK_FAILURE).
104      */
105 	bool onStreamExit(int stream_id, FrameError error_code);
106 
107 /////////////////// Receiving ////////////////////////
108 
109     /**
110      * Callback function invoked by $(D Session.recv) when a frame
111      * is received.  The |user_data| pointer is the third argument passed
112      * in to the call to `http2_session_client_new()` or
113      * `http2_session_server_new()`.
114      *
115      * If frame is HEADERS or PUSH_PROMISE, the ``nva`` 
116      * member of their data structure are always ``NULL`` and 0
117      * respectively.  The header fields are emitted via
118      * $(D onFrameHeader).
119      *
120      * For HEADERS, PUSH_PROMISE and DATA frames, this callback may be
121      * called after stream is closed (see $(D Connector.onStreamExit)). 
122      *
123      * Only HEADERS and DATA frame can signal the end of incoming data.
124      * If ``frame.hd.flags & FrameFlags.END_STREAM`` is nonzero, the
125      * |frame| is the last frame from the remote peer in this stream.
126      *
127      * This callback won't be called for CONTINUATION frames.
128      * HEADERS/PUSH_PROMISE + CONTINUATIONs are treated as single frame.
129      *
130      * If false value is returned, it is treated as fatal error and
131      * $(D Session.recv) and $(D Session.memRecv) functions
132      * immediately return $(D ErrorCode.CALLBACK_FAILURE).
133      */
134     bool onFrame(in Frame frame);
135 
136 	/**
137      * Callback function invoked when a frame header is received.  The
138      * |hd| points to received frame header.
139      *
140      * Unlike $(D Connector.onFrame), this callback will
141      * also be called when frame header of CONTINUATION frame is received.
142      *
143      * If both $(D Connector.onFrameHeader) and
144      * $(D Connector.onHeaders) are set and HEADERS or
145      * PUSH_PROMISE is received, $(D Connector.onFrameReady)
146      * will be called first.
147      *
148      * The implementation of this function must return true if it succeeds.
149      * If false value is returned, it is treated as fatal error and
150      * $(D Session.recv) and `http2_session_mem_recv()` functions
151      * immediately return $(D ErrorCode.CALLBACK_FAILURE).
152      */
153 	bool onFrameHeader(in FrameHeader hd);
154 
155 	/**
156      * Callback function invoked when the reception of header block in
157      * HEADERS or PUSH_PROMISE is started.  Each header header field
158      * will be emitted by $(D Connector.onHeaderField)`.
159      *
160      * The ``frame.hd.flags`` may not have
161      * $(D FrameFlags.END_HEADERS) flag set, which indicates that one
162      * or more CONTINUATION frames are involved.  But the application does
163      * not need to care about that because the header fields are
164      * emitted transparently regardless of CONTINUATION frames.
165      *
166      * If this callback returns false, stream fails with `ErrorCode.CALLBACK_FAILURE`
167      */
168 	bool onHeaders(in Frame frame);
169 
170 
171 	/**
172      * Callback function invoked when a header header field is received
173      * for the |frame|.  The |hf.name| of length |hf.name.length| is header name.
174      * The |hf.value| of length |hf.value.length| is header value.  The |hf.flags| 
175      * is a $(D HeaderFlag).
176      *
177      * If $(D HeaderFlag.NO_INDEX) is set in |hf.flags|, the receiver
178      * must not index this header field when forwarding it to the next
179      * hop.  More specifically, "Literal Header Field never Indexed"
180      * representation must be used in HPACK encoding.
181      *
182      * When this callback is invoked, $(D frame.hd.type) is either
183      * $(D FrameFlags.HEADERS) or $(D FrameFlags.PUSH_PROMISE).  After all
184      * header fields are processed with this callback, and no
185      * error has been detected, $(D Connector.onFrame) will be invoked.  
186      * If there is an error in decompression, $(D Connector.onFrame) for the |frame| 
187      * will not be invoked.
188      *
189      * The |value| may be null if the |value.length| is 0.
190      *
191      * Please note that unless `setNoHTTPMessaging()` is
192      * used, nghttp2 library does perform validation against |hf.name|
193      * and |hf.value| using `hf.validateName()` and
194      * `hf.validateValue()`.  In addition to this, libhttp2
195      * performs vaidation based on HTTP Messaging rule, which is briefly
196      * explained in `HTTP Messaging`_ section.
197      *
198      * If the application uses $(D Session.memRecv), it can enable
199      * $(D pause) to make $(D Session.memRecv) return without processing 
200      * further input bytes.  The memory pointed by |frame|, |name| and |value|
201      * parameters are retained until $(D Session.memRecv) or $(D Session.recv) is called.
202      * The application must retain the input bytes which was used to
203      * produce these parameters, because it may refer to the memory region
204      * included in the input bytes.
205      *
206      * Enabling $(D rst_stream) will close  the stream by issuing RST_STREAM with 
207      * $(D FrameError.INTERNAL_ERROR).  In this case, $(D Connector.onFrame) will 
208      * not be invoked.  If a different error code is desirable, use
209      * $(D submitRstStream) with a desired error code and then
210      * set $(D rst_stream) to true.
211      *
212      * The implementation of this function must return true if it succeeds.
213      * If false is returned, it is treated as $(D ErrorCode.CALLBACK_FAILURE) and
214      * in this case, $(D Session.recv) or $(D Session.memRecv) functions immediately 
215      * return $(D ErrorCode.CALLBACK_FAILURE).
216      */
217 	bool onHeaderField(in Frame frame, HeaderField hf, ref bool pause, ref bool rst_stream);
218 
219 	/**
220      * Callback function invoked when a chunk of data in DATA frame is
221      * received.  The |stream_id| is the stream this DATA frame belongs
222      * to. The |flags| is the flags of DATA frame which this data chunk
223      * is contained.  ``(flags & FrameFlags.END_STREAM) != 0`` does not
224      * necessarily mean this chunk of data is the last one in the stream.
225      * You should use $(D Connector.onFrame) to determine that all data 
226      * frames are received. 
227      *
228      * 
229      * The memory pointed by the |data| is not copied within $(D Session.memRecv)
230      * or $(D Session.recv), so the data provider controls its lifetime. This
231      * can be either $(D Connector.read) for $(D Session.recv), or a $(D ubyte[])
232      * slice from the one provided to $(D Session.memRecv)
233      * 
234      * If the application uses $(D Session.memRecv), it can set |pause|
235      * to make $(D Session.memRecv) return without processing further input bytes. 
236      * 
237      * If the function returns false, $(D Session.memRecv) or $(D Session.recv)
238      * would return with $(D ErrorCode.CALLBACK_FAILURE).
239      */
240 	bool onDataChunk(FrameFlags flags, int stream_id, in ubyte[] data, ref bool pause);
241 
242     /**
243      * Callback function invoked by $(D Session.recv) when an
244      * invalid non-DATA frame is received.  The |error_code| indicates the
245      * error.  It is usually one of the $(D FrameError) but
246      * that is not guaranteed.  When this callback function is invoked,
247      * the library automatically submits either RST_STREAM or GOAWAY
248      * frame.  
249      *
250      * If frame is HEADERS or PUSH_PROMISE, the ``hfa``
251      * member of thee data structure is always ``null``
252      *
253      * If this callback returns false, it is treated as fatal error and
254      * $(D Session.recv) and $(D Session.send) functions
255      * immediately return $(D ErrorCode.CALLBACK_FAILURE).
256      */
257     bool onInvalidFrame(in Frame frame, FrameError error_code);
258 
259 /////////////////// Sending /////////////////////////
260 
261 	/**
262      * Callback function invoked after the non-DATA frame |frame| is not
263      * sent because of the error.  The error is indicated by the
264      * |error_code|, which is one of the values defined in
265      * $(D ErrorCode).  
266      *
267      * If this callback returns false, it is treated as fatal error and
268      * $(D Session.recv) and $(D Session.send) functions
269      * immediately return $(D ErrorCode.CALLBACK_FAILURE).
270      */
271 	bool onFrameFailure(in Frame frame, ErrorCode error_code);
272 
273     /**
274      * Callback function invoked just before the non-DATA frame |frame| is
275      * sent.  
276      *
277      * The implementation of this function must return true if it succeeds.
278      * If this callback returns false, it is treated as fatal error and
279      * $(D Session.recv) and $(D Session.send) functions
280      * immediately return $(D ErrorCode.CALLBACK_FAILURE).
281      */
282     bool onFrameReady(in Frame frame);
283 
284     /**
285      * Callback function invoked after the frame |frame| is sent.  
286      * 
287      * If this callback returns false, it is treated as fatal error and
288      * $(D Session.recv) and $(D Session.send) functions
289      * immediately return $(D ErrorCode.CALLBACK_FAILURE).
290      */
291     bool onFrameSent(in Frame frame);
292 
293     /**
294      * Callback function invoked when the library asks application how
295      * many padding bytes are required for the transmission of the
296      * |frame|.  The application must choose the total length of payload
297      * including padded bytes in range [frame.hd.length, max_payloadlen],
298      * inclusive.  Choosing number not in this range will be treated as
299      * $(D ErrorCode.CALLBACK_FAILURE).  Returning ``frame.hd.length`` 
300      * means no padding is added.  Returning $(D ErrorCode.CALLBACK_FAILURE) will make
301      * $(D Session.send()) function immediately return $(D ErrorCode.CALLBACK_FAILURE).
302      */
303     int selectPaddingLength(in Frame frame, int max_payloadlen)
304 	{
305 		return frame.hd.length;
306 	}
307 
308     /**
309      * Callback function invoked when library wants to get max length of
310      * data to send data to the remote peer.  The implementation of this
311      * function should return a value in the following range.  [1,
312      * min(|session_remote_window_size|, |stream_remote_window_size|,
313      * |remote_max_frame_size|)].  If a value greater than this range is
314      * returned than the max allow value will be used.  Returning a value
315      * smaller than this range is treated as
316      * $(D ErrorCode.CALLBACK_FAILURE).  The |frame_type| is provided
317      * for future extensibility and identifies the type of frame (see
318      * $(D FrameType)) for which to get the length for.
319      * Currently supported frame types are: $(D HTTP2_DATA).
320      *
321      * This callback can be used to control the length in bytes for which
322      * $(D DataProvider) is allowed to send to the
323      * remote endpoint.  This callback is optional.  Returning
324      * $(D ErrorCode.CALLBACK_FAILURE) will signal the entire session
325      * failure..
326      */
327     int maxFrameSize(FrameType frame_type, int stream_id, int session_remote_window_size, int stream_remote_window_size, uint remote_max_frame_size)
328 	{
329 		return min(session_remote_window_size, stream_remote_window_size, remote_max_frame_size);
330 	}
331 
332 
333 }
334 
335 class CallbackConnector : Connector
336 {
337 public:
338 	/**
339      * Callback function invoked when the session wants to send data to
340      * the remote peer.  This callback is not necessary if the
341      * application uses solely $(D Session.memSend) to serialize
342      * data to transmit.
343      */
344 	int delegate(in ubyte[]) write_cb;
345 
346 	/**
347      * Callback function invoked when $(D DataFlags.NO_COPY) is used in $(D DataProvider)
348      * to avoid data copy.
349      */
350 	ErrorCode delegate(in Frame, ubyte[], uint) write_data_cb;
351 
352 	/**
353      * Callback function invoked when the session wants to receive data
354      * from the remote peer.  This callback is not necessary if the
355      * application uses solely `nghttp2_session_mem_recv()` to process
356      * received data.
357      */
358 	int delegate(ubyte[]) read_cb;
359 	
360 	/**
361      * Callback function invoked when the stream is closed.
362      */
363 	bool delegate(int, FrameError) on_stream_exit_cb;
364 
365 	/**
366      * Callback function invoked by $(D Session.recv) when a
367      * frame is received.
368      */
369 	bool delegate(in Frame) on_frame_cb;
370 
371 	/**
372      * Sets callback function invoked when a frame header is received.
373      */
374 	bool delegate(in FrameHeader) on_frame_header_cb;
375 
376 	/**
377      * Callback function invoked when the reception of header block in
378      * HEADERS or PUSH_PROMISE is started.
379      */
380 	bool delegate(in Frame) on_headers_cb;
381 
382 	/**
383      * Callback function invoked when a header name/value pair is
384      * received.
385      */
386 	bool delegate(in Frame, in HeaderField, ref bool, ref bool) on_header_field_cb;
387 
388 	/**
389      * Callback function invoked when a chunk of data in DATA frame is
390      * received.
391      */
392 	bool delegate(FrameFlags, int, in ubyte[], ref bool) on_data_chunk_cb;
393 
394 	/**
395      * Callback function invoked by $(D Session.recv) when an
396      * invalid non-DATA frame is received.
397      */
398 	bool delegate(in Frame, FrameError) on_invalid_frame_cb;
399 
400 	/**
401      * The callback function invoked when a non-DATA frame is not sent
402      * because of an error.
403      */
404 	bool delegate(in Frame, ErrorCode) on_frame_failure_cb;
405 
406 	/**
407      * Callback function invoked before a non-DATA frame is sent.
408      */
409 	bool delegate(in Frame) on_frame_ready_cb;
410 
411 	/**
412      * Callback function invoked after a frame is sent.
413      */
414 	bool delegate(in Frame) on_frame_sent_cb;
415 
416 	/**
417      * Callback function invoked when the library asks application how
418      * many padding bytes are required for the transmission of the given
419      * frame.
420      */
421 	int delegate(in Frame, int) select_padding_length_cb;
422 
423 	/**
424      * The callback function used to determine the length allowed in
425      * $(D DataProvider)
426      */
427 	int delegate(FrameType, int, int, int, uint) max_frame_size_cb;
428 
429 ///////////////// Derived //////////////////
430 override:
431 	int write(in ubyte[] data) 
432 	{ 
433 		if (!write_cb) 
434 			return true; 
435 		return write_cb(data); 
436 	}
437 
438 	ErrorCode writeData(in Frame frame, ubyte[] frame_hd, uint length)
439 	{ 
440 		if (!write_data_cb) 
441 			return ErrorCode.OK; 
442 		return write_data_cb(frame, frame_hd, length); 
443 	}
444 
445 	
446 	int read(ubyte[] data) 
447 	{ 
448 		if (!read_cb) 
449 			return true; 
450 		return read_cb(data); 
451 	}
452 
453 	bool onStreamExit(int stream_id, FrameError error_code)
454 	{ 
455 		if (!on_stream_exit_cb) 
456 			return true; 
457 		return on_stream_exit_cb(stream_id, error_code); 
458 	}
459 
460 	bool onFrame(in Frame frame)
461 	{
462 		if (!on_frame_cb)
463 			return true;
464 		return on_frame_cb(frame);
465 	}
466 	
467 	bool onFrameHeader(in FrameHeader hd)
468 	{
469 		if (!on_frame_header_cb) 
470 			return true; 
471 		return on_frame_header_cb(hd); 
472 	}
473 	
474 	bool onHeaders(in Frame frame)
475 	{
476 		if (!on_headers_cb)
477 			return true;
478 		return on_headers_cb(frame);
479 	}
480 	
481 	bool onHeaderField(in Frame frame, HeaderField hf, ref bool pause, ref bool rst_stream)
482 	{
483 		if (!on_header_field_cb)
484 			return true;
485 		return on_header_field_cb(frame, hf, pause, rst_stream);
486 	}
487 	
488 	bool onDataChunk(FrameFlags flags, int stream_id, in ubyte[] data, ref bool pause)
489 	{
490 		if (!on_data_chunk_cb)
491 			return true;
492 		return on_data_chunk_cb(flags, stream_id, data, pause);
493 	}
494 	
495 	bool onInvalidFrame(in Frame frame, FrameError error_code)
496 	{
497 		if (!on_invalid_frame_cb)
498 			return true;
499 		return on_invalid_frame_cb(frame, error_code);
500 	}
501 	
502 	bool onFrameFailure(in Frame frame, ErrorCode error_code)
503 	{
504 		if (!on_frame_failure_cb)
505 			return true;
506 		return on_frame_failure_cb(frame, error_code);
507 	}
508 	
509 	bool onFrameReady(in Frame frame)
510 	{
511 		if (!on_frame_ready_cb)
512 			return true;
513 		return on_frame_ready_cb(frame);
514 	}
515 	
516 	bool onFrameSent(in Frame frame)
517 	{
518 		if (!on_frame_sent_cb)
519 			return true;
520 		return on_frame_sent_cb(frame);
521 	}
522 	
523 	int selectPaddingLength(in Frame frame, int max_payloadlen)
524 	{
525 		if (!select_padding_length_cb)
526 			return super.selectPaddingLength(frame, max_payloadlen);
527 		return select_padding_length_cb(frame, max_payloadlen);
528 	}
529 	
530 	int maxFrameSize(FrameType frame_type, int stream_id, int session_remote_window_size, int stream_remote_window_size, uint remote_max_frame_size)
531 	{
532 		if (!max_frame_size_cb)
533 			return super.maxFrameSize(frame_type, stream_id, session_remote_window_size, stream_remote_window_size, remote_max_frame_size);
534 		return max_frame_size_cb(frame_type, stream_id, session_remote_window_size, stream_remote_window_size, remote_max_frame_size);
535 	}
536 	
537 }