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 public:
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, string reason = "");
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           import std.algorithm : min;
330 		return min(session_remote_window_size, stream_remote_window_size, remote_max_frame_size);
331 	}
332 
333 
334 }
335 
336 class CallbackConnector : Connector
337 {
338 public:
339 	/**
340      * Callback function invoked when the session wants to send data to
341      * the remote peer.  This callback is not necessary if the
342      * application uses solely $(D Session.memSend) to serialize
343      * data to transmit.
344      */
345 	int delegate(in ubyte[]) write_cb;
346 
347 	/**
348      * Callback function invoked when $(D DataFlags.NO_COPY) is used in $(D DataProvider)
349      * to avoid data copy.
350      */
351 	ErrorCode delegate(in Frame, ubyte[], uint) write_data_cb;
352 
353 	/**
354      * Callback function invoked when the session wants to receive data
355      * from the remote peer.  This callback is not necessary if the
356      * application uses solely `nghttp2_session_mem_recv()` to process
357      * received data.
358      */
359 	int delegate(ubyte[]) read_cb;
360 	
361 	/**
362      * Callback function invoked when the stream is closed.
363      */
364 	bool delegate(int, FrameError) on_stream_exit_cb;
365 
366 	/**
367      * Callback function invoked by $(D Session.recv) when a
368      * frame is received.
369      */
370 	bool delegate(in Frame) on_frame_cb;
371 
372 	/**
373      * Sets callback function invoked when a frame header is received.
374      */
375 	bool delegate(in FrameHeader) on_frame_header_cb;
376 
377 	/**
378      * Callback function invoked when the reception of header block in
379      * HEADERS or PUSH_PROMISE is started.
380      */
381 	bool delegate(in Frame) on_headers_cb;
382 
383 	/**
384      * Callback function invoked when a header name/value pair is
385      * received.
386      */
387 	bool delegate(in Frame, in HeaderField, ref bool, ref bool) on_header_field_cb;
388 
389 	/**
390      * Callback function invoked when a chunk of data in DATA frame is
391      * received.
392      */
393 	bool delegate(FrameFlags, int, in ubyte[], ref bool) on_data_chunk_cb;
394 
395 	/**
396      * Callback function invoked by $(D Session.recv) when an
397      * invalid non-DATA frame is received.
398      */
399 	bool delegate(in Frame, FrameError) on_invalid_frame_cb;
400 
401 	/**
402      * The callback function invoked when a non-DATA frame is not sent
403      * because of an error.
404      */
405 	bool delegate(in Frame, ErrorCode) on_frame_failure_cb;
406 
407 	/**
408      * Callback function invoked before a non-DATA frame is sent.
409      */
410 	bool delegate(in Frame) on_frame_ready_cb;
411 
412 	/**
413      * Callback function invoked after a frame is sent.
414      */
415 	bool delegate(in Frame) on_frame_sent_cb;
416 
417 	/**
418      * Callback function invoked when the library asks application how
419      * many padding bytes are required for the transmission of the given
420      * frame.
421      */
422 	int delegate(in Frame, int) select_padding_length_cb;
423 
424 	/**
425      * The callback function used to determine the length allowed in
426      * $(D DataProvider)
427      */
428 	int delegate(FrameType, int, int, int, uint) max_frame_size_cb;
429 
430 ///////////////// Derived //////////////////
431 override:
432 	int write(in ubyte[] data) 
433 	{ 
434 		if (!write_cb) 
435 			return true; 
436 		return write_cb(data); 
437 	}
438 
439 	ErrorCode writeData(in Frame frame, ubyte[] frame_hd, uint length)
440 	{ 
441 		if (!write_data_cb) 
442 			return ErrorCode.OK; 
443 		return write_data_cb(frame, frame_hd, length); 
444 	}
445 
446 	
447 	int read(ubyte[] data) 
448 	{ 
449 		if (!read_cb) 
450 			return true; 
451 		return read_cb(data); 
452 	}
453 
454 	bool onStreamExit(int stream_id, FrameError error_code)
455 	{ 
456 		if (!on_stream_exit_cb) 
457 			return true; 
458 		return on_stream_exit_cb(stream_id, error_code); 
459 	}
460 
461 	bool onFrame(in Frame frame)
462 	{
463 		if (!on_frame_cb)
464 			return true;
465 		return on_frame_cb(frame);
466 	}
467 	
468 	bool onFrameHeader(in FrameHeader hd)
469 	{
470 		if (!on_frame_header_cb) 
471 			return true; 
472 		return on_frame_header_cb(hd); 
473 	}
474 	
475 	bool onHeaders(in Frame frame)
476 	{
477 		if (!on_headers_cb)
478 			return true;
479 		return on_headers_cb(frame);
480 	}
481 	
482 	bool onHeaderField(in Frame frame, HeaderField hf, ref bool pause, ref bool rst_stream)
483 	{
484 		if (!on_header_field_cb)
485 			return true;
486 		return on_header_field_cb(frame, hf, pause, rst_stream);
487 	}
488 	
489 	bool onDataChunk(FrameFlags flags, int stream_id, in ubyte[] data, ref bool pause)
490 	{
491 		if (!on_data_chunk_cb)
492 			return true;
493 		return on_data_chunk_cb(flags, stream_id, data, pause);
494 	}
495 	
496 	bool onInvalidFrame(in Frame frame, FrameError error_code, string reason)
497 	{
498 		if (!on_invalid_frame_cb)
499 			return true;
500 		return on_invalid_frame_cb(frame, error_code);
501 	}
502 	
503 	bool onFrameFailure(in Frame frame, ErrorCode error_code)
504 	{
505 		if (!on_frame_failure_cb)
506 			return true;
507 		return on_frame_failure_cb(frame, error_code);
508 	}
509 	
510 	bool onFrameReady(in Frame frame)
511 	{
512 		if (!on_frame_ready_cb)
513 			return true;
514 		return on_frame_ready_cb(frame);
515 	}
516 	
517 	bool onFrameSent(in Frame frame)
518 	{
519 		if (!on_frame_sent_cb)
520 			return true;
521 		return on_frame_sent_cb(frame);
522 	}
523 	
524 	int selectPaddingLength(in Frame frame, int max_payloadlen)
525 	{
526 		if (!select_padding_length_cb)
527 			return super.selectPaddingLength(frame, max_payloadlen);
528 		return select_padding_length_cb(frame, max_payloadlen);
529 	}
530 	
531 	int maxFrameSize(FrameType frame_type, int stream_id, int session_remote_window_size, int stream_remote_window_size, uint remote_max_frame_size)
532 	{
533 		if (!max_frame_size_cb)
534 			return super.maxFrameSize(frame_type, stream_id, session_remote_window_size, stream_remote_window_size, remote_max_frame_size);
535 		return max_frame_size_cb(frame_type, stream_id, session_remote_window_size, stream_remote_window_size, remote_max_frame_size);
536 	}
537 	
538 }