2012-11-20 17:29:39 +01:00
|
|
|
/*
|
2014-03-30 12:09:21 +02:00
|
|
|
* nghttp2 - HTTP/2 C Library
|
2012-11-20 17:29:39 +01:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2013-11-04 09:53:57 +01:00
|
|
|
#ifndef SHRPX_HTTP2_SESSION_H
|
|
|
|
#define SHRPX_HTTP2_SESSION_H
|
2012-11-20 17:29:39 +01:00
|
|
|
|
|
|
|
#include "shrpx.h"
|
|
|
|
|
2015-03-10 16:42:18 +01:00
|
|
|
#include <unordered_set>
|
2013-09-23 17:19:53 +02:00
|
|
|
#include <memory>
|
2012-11-20 17:29:39 +01:00
|
|
|
|
|
|
|
#include <openssl/ssl.h>
|
|
|
|
|
2014-12-27 18:59:06 +01:00
|
|
|
#include <ev.h>
|
2012-11-20 17:29:39 +01:00
|
|
|
|
2013-07-12 17:19:03 +02:00
|
|
|
#include <nghttp2/nghttp2.h>
|
2012-11-20 17:29:39 +01:00
|
|
|
|
2013-02-09 08:42:01 +01:00
|
|
|
#include "http-parser/http_parser.h"
|
|
|
|
|
2015-02-04 13:15:58 +01:00
|
|
|
#include "shrpx_connection.h"
|
|
|
|
#include "buffer.h"
|
2015-03-11 13:35:47 +01:00
|
|
|
#include "template.h"
|
2014-12-27 18:59:06 +01:00
|
|
|
|
|
|
|
using namespace nghttp2;
|
|
|
|
|
2012-11-20 17:29:39 +01:00
|
|
|
namespace shrpx {
|
|
|
|
|
2013-11-04 09:53:57 +01:00
|
|
|
class Http2DownstreamConnection;
|
2015-03-10 13:54:29 +01:00
|
|
|
class Worker;
|
2015-03-10 15:11:22 +01:00
|
|
|
class ConnectBlocker;
|
2012-11-20 17:29:39 +01:00
|
|
|
|
|
|
|
struct StreamData {
|
2015-03-11 13:35:47 +01:00
|
|
|
StreamData *dlnext, *dlprev;
|
2013-11-04 09:53:57 +01:00
|
|
|
Http2DownstreamConnection *dconn;
|
2012-11-20 17:29:39 +01:00
|
|
|
};
|
|
|
|
|
2013-11-04 09:53:57 +01:00
|
|
|
class Http2Session {
|
2012-11-20 17:29:39 +01:00
|
|
|
public:
|
2015-03-10 15:11:22 +01:00
|
|
|
Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx,
|
|
|
|
ConnectBlocker *connect_blocker, Worker *worker);
|
2014-12-27 18:59:06 +01:00
|
|
|
~Http2Session();
|
2012-11-20 17:29:39 +01:00
|
|
|
|
2012-11-22 13:46:15 +01:00
|
|
|
int check_cert();
|
|
|
|
|
2014-12-15 15:34:00 +01:00
|
|
|
// If hard is true, all pending requests are abandoned and
|
|
|
|
// associated ClientHandlers will be deleted.
|
|
|
|
int disconnect(bool hard = false);
|
2012-11-20 17:29:39 +01:00
|
|
|
int initiate_connection();
|
|
|
|
|
2013-11-04 09:53:57 +01:00
|
|
|
void add_downstream_connection(Http2DownstreamConnection *dconn);
|
|
|
|
void remove_downstream_connection(Http2DownstreamConnection *dconn);
|
2012-11-20 17:29:39 +01:00
|
|
|
|
|
|
|
void remove_stream_data(StreamData *sd);
|
|
|
|
|
2014-11-27 15:39:04 +01:00
|
|
|
int submit_request(Http2DownstreamConnection *dconn, int32_t pri,
|
|
|
|
const nghttp2_nv *nva, size_t nvlen,
|
2013-07-12 17:19:03 +02:00
|
|
|
const nghttp2_data_provider *data_prd);
|
2012-11-20 17:29:39 +01:00
|
|
|
|
2014-08-23 10:34:56 +02:00
|
|
|
int submit_rst_stream(int32_t stream_id, uint32_t error_code);
|
2012-11-20 17:29:39 +01:00
|
|
|
|
2014-01-18 08:12:03 +01:00
|
|
|
int submit_priority(Http2DownstreamConnection *dconn, int32_t pri);
|
|
|
|
|
2014-08-23 10:34:56 +02:00
|
|
|
int terminate_session(uint32_t error_code);
|
2013-10-31 13:45:17 +01:00
|
|
|
|
2014-11-27 15:39:04 +01:00
|
|
|
nghttp2_session *get_session() const;
|
2013-10-29 16:07:35 +01:00
|
|
|
|
2012-11-21 15:47:48 +01:00
|
|
|
bool get_flow_control() const;
|
|
|
|
|
2013-11-04 09:53:57 +01:00
|
|
|
int resume_data(Http2DownstreamConnection *dconn);
|
2012-11-20 17:29:39 +01:00
|
|
|
|
2015-03-28 12:19:17 +01:00
|
|
|
int connection_made();
|
2012-11-20 17:29:39 +01:00
|
|
|
|
2014-12-27 18:59:06 +01:00
|
|
|
int do_read();
|
|
|
|
int do_write();
|
|
|
|
|
2012-11-20 17:29:39 +01:00
|
|
|
int on_read();
|
|
|
|
int on_write();
|
|
|
|
|
2014-12-27 18:59:06 +01:00
|
|
|
int connected();
|
|
|
|
int read_clear();
|
|
|
|
int write_clear();
|
|
|
|
int tls_handshake();
|
|
|
|
int read_tls();
|
|
|
|
int write_tls();
|
|
|
|
|
|
|
|
int downstream_read_proxy();
|
|
|
|
int downstream_connect_proxy();
|
2013-02-09 08:42:01 +01:00
|
|
|
|
2014-12-27 18:59:06 +01:00
|
|
|
int downstream_read();
|
|
|
|
int downstream_write();
|
2012-11-20 17:29:39 +01:00
|
|
|
|
2014-12-27 18:59:06 +01:00
|
|
|
int noop();
|
|
|
|
|
|
|
|
void signal_write();
|
|
|
|
|
|
|
|
struct ev_loop *get_loop() const;
|
|
|
|
|
|
|
|
ev_io *get_wev();
|
2012-11-20 17:29:39 +01:00
|
|
|
|
|
|
|
int get_state() const;
|
2013-02-09 08:42:01 +01:00
|
|
|
void set_state(int state);
|
2012-11-20 17:29:39 +01:00
|
|
|
|
2014-12-27 18:59:06 +01:00
|
|
|
void start_settings_timer();
|
2013-10-31 13:45:17 +01:00
|
|
|
void stop_settings_timer();
|
|
|
|
|
2014-11-27 15:39:04 +01:00
|
|
|
SSL *get_ssl() const;
|
2014-04-26 16:00:58 +02:00
|
|
|
|
2014-07-25 14:26:03 +02:00
|
|
|
int consume(int32_t stream_id, size_t len);
|
2014-07-02 16:20:45 +02:00
|
|
|
|
nghttpx: Check HTTP/2 downstream connection after certain idle time
Previously when requests are issued to HTTP/2 downstream connection,
but it turns out that connection is down, handlers of those requests
are deleted. In some situations, we only know connection is down when
we write something to network, so we'd like to handle this kind of
situation in more robust manner. In this change, certain seconds
passed after last network activity, we first issue PING frame to
downstream connection before issuing new HTTP request. If writing
PING frame is failed, it means connection was lost. In this case,
instead of deleting handler, pending requests are migrated to new
HTTP2/ downstream connection, so that it can continue without
affecting upstream connection.
2014-12-08 17:30:15 +01:00
|
|
|
// Returns true if request can be issued on downstream connection.
|
|
|
|
bool can_push_request() const;
|
|
|
|
// Initiates the connection checking if downstream connection has
|
|
|
|
// been established and connection checking is required.
|
|
|
|
void start_checking_connection();
|
2015-03-09 13:22:31 +01:00
|
|
|
// Resets connection check timer to timeout |t|. After timeout, we
|
|
|
|
// require connection checking. If connection checking is already
|
|
|
|
// enabled, this timeout is for PING ACK timeout.
|
|
|
|
void reset_connection_check_timer(ev_tstamp t);
|
2015-03-10 16:27:51 +01:00
|
|
|
void reset_connection_check_timer_if_not_checking();
|
nghttpx: Check HTTP/2 downstream connection after certain idle time
Previously when requests are issued to HTTP/2 downstream connection,
but it turns out that connection is down, handlers of those requests
are deleted. In some situations, we only know connection is down when
we write something to network, so we'd like to handle this kind of
situation in more robust manner. In this change, certain seconds
passed after last network activity, we first issue PING frame to
downstream connection before issuing new HTTP request. If writing
PING frame is failed, it means connection was lost. In this case,
instead of deleting handler, pending requests are migrated to new
HTTP2/ downstream connection, so that it can continue without
affecting upstream connection.
2014-12-08 17:30:15 +01:00
|
|
|
// Signals that connection is alive. Internally
|
|
|
|
// reset_connection_check_timer() is called.
|
2014-12-27 18:59:06 +01:00
|
|
|
void connection_alive();
|
nghttpx: Check HTTP/2 downstream connection after certain idle time
Previously when requests are issued to HTTP/2 downstream connection,
but it turns out that connection is down, handlers of those requests
are deleted. In some situations, we only know connection is down when
we write something to network, so we'd like to handle this kind of
situation in more robust manner. In this change, certain seconds
passed after last network activity, we first issue PING frame to
downstream connection before issuing new HTTP request. If writing
PING frame is failed, it means connection was lost. In this case,
instead of deleting handler, pending requests are migrated to new
HTTP2/ downstream connection, so that it can continue without
affecting upstream connection.
2014-12-08 17:30:15 +01:00
|
|
|
// Change connection check state.
|
|
|
|
void set_connection_check_state(int state);
|
2015-03-09 13:22:31 +01:00
|
|
|
int get_connection_check_state() const;
|
nghttpx: Check HTTP/2 downstream connection after certain idle time
Previously when requests are issued to HTTP/2 downstream connection,
but it turns out that connection is down, handlers of those requests
are deleted. In some situations, we only know connection is down when
we write something to network, so we'd like to handle this kind of
situation in more robust manner. In this change, certain seconds
passed after last network activity, we first issue PING frame to
downstream connection before issuing new HTTP request. If writing
PING frame is failed, it means connection was lost. In this case,
instead of deleting handler, pending requests are migrated to new
HTTP2/ downstream connection, so that it can continue without
affecting upstream connection.
2014-12-08 17:30:15 +01:00
|
|
|
|
2014-12-27 18:59:06 +01:00
|
|
|
bool should_hard_fail() const;
|
|
|
|
|
2015-02-17 15:15:53 +01:00
|
|
|
void submit_pending_requests();
|
|
|
|
|
2015-03-10 13:54:29 +01:00
|
|
|
size_t get_addr_idx() const;
|
|
|
|
|
2012-11-20 17:29:39 +01:00
|
|
|
enum {
|
2013-02-09 08:42:01 +01:00
|
|
|
// Disconnected
|
2012-11-20 17:29:39 +01:00
|
|
|
DISCONNECTED,
|
2013-02-09 08:42:01 +01:00
|
|
|
// Connecting proxy and making CONNECT request
|
|
|
|
PROXY_CONNECTING,
|
|
|
|
// Tunnel is established with proxy
|
|
|
|
PROXY_CONNECTED,
|
|
|
|
// Establishing tunnel is failed
|
|
|
|
PROXY_FAILED,
|
|
|
|
// Connecting to downstream and/or performing SSL/TLS handshake
|
2012-11-20 17:29:39 +01:00
|
|
|
CONNECTING,
|
2013-02-09 08:42:01 +01:00
|
|
|
// Connected to downstream
|
2014-12-27 18:59:06 +01:00
|
|
|
CONNECTED,
|
|
|
|
// Connection is started to fail
|
|
|
|
CONNECT_FAILING,
|
2012-11-20 17:29:39 +01:00
|
|
|
};
|
2014-01-19 10:07:50 +01:00
|
|
|
|
nghttpx: Check HTTP/2 downstream connection after certain idle time
Previously when requests are issued to HTTP/2 downstream connection,
but it turns out that connection is down, handlers of those requests
are deleted. In some situations, we only know connection is down when
we write something to network, so we'd like to handle this kind of
situation in more robust manner. In this change, certain seconds
passed after last network activity, we first issue PING frame to
downstream connection before issuing new HTTP request. If writing
PING frame is failed, it means connection was lost. In this case,
instead of deleting handler, pending requests are migrated to new
HTTP2/ downstream connection, so that it can continue without
affecting upstream connection.
2014-12-08 17:30:15 +01:00
|
|
|
enum {
|
|
|
|
// Connection checking is not required
|
|
|
|
CONNECTION_CHECK_NONE,
|
|
|
|
// Connection checking is required
|
|
|
|
CONNECTION_CHECK_REQUIRED,
|
|
|
|
// Connection checking has been started
|
|
|
|
CONNECTION_CHECK_STARTED
|
|
|
|
};
|
|
|
|
|
2015-02-04 13:15:58 +01:00
|
|
|
using ReadBuf = Buffer<8192>;
|
|
|
|
using WriteBuf = Buffer<32768>;
|
2015-01-08 13:28:52 +01:00
|
|
|
|
2012-11-20 17:29:39 +01:00
|
|
|
private:
|
2015-02-04 13:15:58 +01:00
|
|
|
Connection conn_;
|
2014-12-27 18:59:06 +01:00
|
|
|
ev_timer settings_timer_;
|
2015-03-09 13:22:31 +01:00
|
|
|
// This timer has 2 purpose: when it first timeout, set
|
|
|
|
// connection_check_state_ = CONNECTION_CHECK_REQUIRED. After
|
|
|
|
// connection check has started, this timer is started again and
|
|
|
|
// traps PING ACK timeout.
|
2014-12-27 18:59:06 +01:00
|
|
|
ev_timer connchk_timer_;
|
2015-03-11 13:35:47 +01:00
|
|
|
DList<Http2DownstreamConnection> dconns_;
|
|
|
|
DList<StreamData> streams_;
|
2014-12-27 18:59:06 +01:00
|
|
|
std::function<int(Http2Session &)> read_, write_;
|
|
|
|
std::function<int(Http2Session &)> on_read_, on_write_;
|
2013-12-06 15:17:38 +01:00
|
|
|
// Used to parse the response from HTTP proxy
|
|
|
|
std::unique_ptr<http_parser> proxy_htp_;
|
2015-03-10 13:54:29 +01:00
|
|
|
Worker *worker_;
|
2015-03-10 15:11:22 +01:00
|
|
|
ConnectBlocker *connect_blocker_;
|
2013-02-22 13:54:07 +01:00
|
|
|
// NULL if no TLS is configured
|
2012-11-20 17:29:39 +01:00
|
|
|
SSL_CTX *ssl_ctx_;
|
2013-12-06 15:17:38 +01:00
|
|
|
nghttp2_session *session_;
|
2014-12-27 18:59:06 +01:00
|
|
|
const uint8_t *data_pending_;
|
|
|
|
size_t data_pendinglen_;
|
2015-03-10 13:54:29 +01:00
|
|
|
// index of get_config()->downstream_addrs this object uses
|
|
|
|
size_t addr_idx_;
|
2012-11-20 17:29:39 +01:00
|
|
|
int state_;
|
nghttpx: Check HTTP/2 downstream connection after certain idle time
Previously when requests are issued to HTTP/2 downstream connection,
but it turns out that connection is down, handlers of those requests
are deleted. In some situations, we only know connection is down when
we write something to network, so we'd like to handle this kind of
situation in more robust manner. In this change, certain seconds
passed after last network activity, we first issue PING frame to
downstream connection before issuing new HTTP request. If writing
PING frame is failed, it means connection was lost. In this case,
instead of deleting handler, pending requests are migrated to new
HTTP2/ downstream connection, so that it can continue without
affecting upstream connection.
2014-12-08 17:30:15 +01:00
|
|
|
int connection_check_state_;
|
2012-11-21 15:47:48 +01:00
|
|
|
bool flow_control_;
|
2015-01-08 13:28:52 +01:00
|
|
|
WriteBuf wb_;
|
|
|
|
ReadBuf rb_;
|
2012-11-20 17:29:39 +01:00
|
|
|
};
|
|
|
|
|
2015-02-24 07:21:10 +01:00
|
|
|
nghttp2_session_callbacks *create_http2_downstream_callbacks();
|
|
|
|
|
2012-11-20 17:29:39 +01:00
|
|
|
} // namespace shrpx
|
|
|
|
|
2013-11-04 09:53:57 +01:00
|
|
|
#endif // SHRPX_HTTP2_SESSION_H
|