blob: 78894af080b2db9305a21d349e922a8ba3bee371 [file] [log] [blame]
#ifndef __http2_adaptor_h__
#define __http2_adaptor_h__ 1
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "adaptors/http_common.h"
#include "server_private.h"
#include "qpid/dispatch/alloc.h"
#include "qpid/dispatch/atomic.h"
#include "qpid/dispatch/compose.h"
#include "qpid/dispatch/ctools.h"
#include "qpid/dispatch/log.h"
#include "qpid/dispatch/protocol_adaptor.h"
#include "qpid/dispatch/server.h"
#include "qpid/dispatch/threading.h"
#include <nghttp2/nghttp2.h>
#include <time.h>
size_t QD_HTTP2_BUFFER_SIZE = 16384;
size_t NUM_QD_BUFFERS_IN_ONE_HTTP2_BUFFER = 32;
size_t MAX_BUFFERS = 16;
size_t HTTP2_DATA_FRAME_HEADER_LENGTH = 9;
typedef struct qdr_http2_session_data_t qdr_http2_session_data_t;
typedef struct qdr_http2_stream_data_t qdr_http2_stream_data_t;
typedef struct qdr_http2_connection_t qdr_http2_connection_t;
typedef struct qd_http2_buffer_t qd_http2_buffer_t;
/**
* Stream status
*/
typedef enum {
QD_STREAM_OPEN,
QD_STREAM_HALF_CLOSED,
QD_STREAM_FULLY_CLOSED
} qd_http2_stream_status_t;
DEQ_DECLARE(qdr_http2_stream_data_t, qd_http2_stream_data_list_t);
DEQ_DECLARE(qd_http2_buffer_t, qd_http2_buffer_list_t);
DEQ_DECLARE(qdr_http2_connection_t, qdr_http2_connection_list_t);
struct qdr_http2_session_data_t {
qdr_http2_connection_t *conn; // Connection associated with the session_data
nghttp2_session *session; // A pointer to the nghttp2s' session object
qd_http2_stream_data_list_t streams; // A session can have many streams.
qd_http2_buffer_list_t buffs; // Buffers for writing
};
struct qdr_http2_stream_data_t {
qdr_http2_session_data_t *session_data;
void *context;
char *reply_to;
char *remote_site; //for stats:
char *method; //for stats, also used in the subject field of AMQP request message.
char *request_status; //for stats, also used in the subject field of AMQP response message.
qdr_delivery_t *in_dlv;
qdr_delivery_t *out_dlv;
uint64_t incoming_id;
uint64_t outgoing_id;
uint64_t out_dlv_local_disposition;
qdr_link_t *in_link;
qdr_link_t *out_link;
qd_message_t *message;
qd_composed_field_t *app_properties;
qd_composed_field_t *footer_properties;
qd_buffer_list_t body_buffers;
qd_message_stream_data_t *curr_stream_data;
qd_iterator_t *curr_stream_data_iter; // points to the data contained in the stream_data/raw_buffers
qd_message_stream_data_t *next_stream_data;
qd_message_stream_data_t *footer_stream_data;
DEQ_LINKS(qdr_http2_stream_data_t);
qd_message_stream_data_result_t curr_stream_data_result;
qd_message_stream_data_result_t next_stream_data_result;
int payload_handled;
int in_link_credit; // provided by router
int32_t stream_id;
qd_http2_stream_status_t status;
bool entire_footer_arrived;
bool entire_header_arrived;
bool out_msg_header_sent;
bool out_msg_body_sent;
bool use_footer_properties;
bool full_payload_handled; // applies to the sending side.
bool out_msg_has_body;
bool out_msg_data_flag_eof;
bool out_msg_has_footer;
bool out_msg_send_complete; // we use this flag to save the send_complete flag because the delivery and message associated with this stream might have been freed.
bool disp_updated; // Has the disposition already been set on the out_dlv
bool disp_applied; // Has the disp been applied to the out_dlv. The stream is ready to be freed now.
bool header_and_props_composed; // true if the header and properties of the inbound message have already been composed so we don't have to do it again.
bool stream_force_closed;
bool in_dlv_decrefed;
bool out_dlv_decrefed;
bool body_data_added_to_msg;
int bytes_in;
int bytes_out;
qd_timestamp_t start;
qd_timestamp_t stop;
};
struct qdr_http2_connection_t {
qd_handler_context_t context;
qdr_connection_t *qdr_conn;
pn_raw_connection_t *pn_raw_conn;
pn_raw_buffer_t read_buffers[4];
qd_timer_t *activate_timer;
qd_timer_t *ping_timer; // This timer is used to send a ping frame on the egress connection every 4 seconds.
qd_http_bridge_config_t *config;
qd_server_t *server;
uint64_t conn_id;
qdr_http2_session_data_t *session_data;
char *remote_address;
qdr_link_t *stream_dispatcher;
qdr_http2_stream_data_t *stream_dispatcher_stream_data;
uint64_t stream_dispatcher_id;
nghttp2_data_provider data_prd;
qd_http2_buffer_list_t granted_read_buffs; //buffers for reading
time_t prev_ping; // Time the previous PING frame was sent on egress connection.
time_t last_pn_raw_conn_read; // The last time a PN_RAW_CONNECTION_READ event was invoked with more than zero bytes on an egress connection.
bool connection_established;
bool grant_initial_buffers;
bool ingress;
bool timer_scheduled;
bool client_magic_sent;
bool woken_by_ping;
bool first_pinged;
bool delete_egress_connections; // If set to true, the egress qdr_connection_t and qdr_http2_connection_t objects will be deleted
bool goaway_received;
sys_atomic_t raw_closed_read;
sys_atomic_t raw_closed_write;
bool q2_blocked; // send a connection level WINDOW_UPDATE frame to tell the client to stop sending data.
sys_atomic_t q2_restart; // signal to resume receive
DEQ_LINKS(qdr_http2_connection_t);
};
struct qd_http2_buffer_t {
unsigned int size; ///< Size of data content
unsigned char content[16393]; // 16k max content + 9 bytes for the HTTP2 header, 16384 + 9 = 16393
DEQ_LINKS(qd_http2_buffer_t);
};
static inline unsigned char *qd_http2_buffer_base(const qd_http2_buffer_t *buf)
{
return (unsigned char*) &buf->content[0];
}
/**
* Return a pointer to the first unused byte in the buffer.
* @param buf A pointer to an allocated buffer
* @return A pointer to the first free octet in the buffer, the insert point for new data.
*/
static inline unsigned char *qd_http2_buffer_cursor(const qd_http2_buffer_t *buf)
{
return ( (unsigned char*) &(buf->content[0]) ) + buf->size;
}
/**
* Return remaining capacity at end of buffer.
* @param buf A pointer to an allocated buffer
* @return The number of octets in the buffer's free space, how many octets may be inserted.
*/
static inline size_t qd_http2_buffer_capacity(const qd_http2_buffer_t *buf)
{
return QD_HTTP2_BUFFER_SIZE - buf->size;
}
/**
* Return the size of the buffers data content.
* @param buf A pointer to an allocated buffer
* @return The number of octets of data in the buffer
*/
static inline size_t qd_http2_buffer_size(const qd_http2_buffer_t *buf)
{
return buf->size;
}
/**
* Notify the buffer that octets have been inserted at the buffer's cursor. This will advance the
* cursor by len octets.
*
* @param buf A pointer to an allocated buffer
* @param len The number of octets that have been appended to the buffer
*/
static inline void qd_http2_buffer_insert(qd_http2_buffer_t *buf, size_t len)
{
buf->size += len;
assert(buf->size <= QD_HTTP2_BUFFER_SIZE + HTTP2_DATA_FRAME_HEADER_LENGTH);
}
ALLOC_DECLARE(qdr_http2_session_data_t);
ALLOC_DECLARE(qdr_http2_stream_data_t);
ALLOC_DECLARE(qdr_http2_connection_t);
ALLOC_DECLARE(qd_http2_buffer_t);
#endif // __http2_adaptor_h__