return send;
}
-int http_write(uv_write_t *req, uv_handle_t *handle, knot_pkt_t *pkt, uv_write_cb cb)
+int http_write(uv_write_t *req, uv_handle_t *handle, int32_t stream_id, knot_pkt_t *pkt, uv_write_cb cb)
{
- if (!pkt || !handle || !handle->data) {
+ if (!pkt || !handle || !handle->data || stream_id < 0) {
return kr_error(EINVAL);
}
MAKE_NV("content-length", 14, size, size_len)
};
- int ret = nghttp2_submit_response(http_ctx->session, http_ctx->request_stream_id, hdrs, sizeof(hdrs)/sizeof(*hdrs), &data_prd);
+ int ret = nghttp2_submit_response(http_ctx->session, stream_id, hdrs, sizeof(hdrs)/sizeof(*hdrs), &data_prd);
if (ret != 0) {
kr_log_error("[%s] nghttp2_submit_response failed: %s (%d)\n", server_logstring, nghttp2_strerror(ret), ret);
return kr_error(EIO);
kr_log_error("[%s] nghttp2_session_send failed: %s (%d)\n", server_logstring, nghttp2_strerror(ret), ret);
return kr_error(EIO);
}
-
+
/* The data is now accepted in gnutls internal buffers, the message can be treated as sent */
req->handle = (uv_stream_t *)handle;
cb(req, 0);
}
nghttp2_session_del(ctx->session);
ctx->session = NULL;
-}
\ No newline at end of file
+}
struct http_ctx_t* http_new(http_send_callback cb, void *user_ctx);
ssize_t http_process_input_data(struct session *s, const uint8_t *buf, ssize_t nread);
-int http_write(uv_write_t *req, uv_handle_t *handle, knot_pkt_t *pkt, uv_write_cb cb);
-void http_free(struct http_ctx_t *ctx);
\ No newline at end of file
+int http_write(uv_write_t *req, uv_handle_t *handle, int32_t stream_id, knot_pkt_t *pkt, uv_write_cb cb);
+void http_free(struct http_ctx_t *ctx);
// return kr_error(EIO);
//}
//memcpy(buffer_backup, buffer, buffer_len);
-
+
uv_write_t *req = (uv_write_t *)calloc(1, sizeof(uv_write_t));
if (!req) {
return kr_error(EIO);
}
-
+
const uv_buf_t uv_buffer = {
//.base = buffer_backup,
.base = buffer,
const knot_pkt_t *packet;
struct kr_request_qsource_flags flags;
size_t size;
+ int32_t stream_id;
} qsource;
struct {
unsigned int rtt;
req->qsource.flags.tcp = session_get_handle(session)->type == UV_TCP;
req->qsource.flags.tls = session_flags(session)->has_tls;
req->qsource.flags.http = session_flags(session)->has_http;
+ req->qsource.stream_id = -1;
+ if (req->qsource.flags.http) {
+ struct http_ctx_t *http_ctx = session_http_get_server_ctx(session);
+ // TODO maybe assert?
+ if (http_ctx) {
+ req->qsource.stream_id = http_ctx->request_stream_id;
+ }
+ }
/* We need to store a copy of peer address. */
memcpy(&ctx->source.addr.ip, peer, kr_sockaddr_len(peer));
req->qsource.addr = &ctx->source.addr.ip;
if (session_flags(session)->has_http) {
uv_write_t *write_req = (uv_write_t *)ioreq;
write_req->data = task;
- ret = http_write(write_req, handle, pkt, &on_write);
+ ret = http_write(write_req, handle, ctx->req.qsource.stream_id, pkt, &on_write);
} else if (session_flags(session)->has_tls) {
uv_write_t *write_req = (uv_write_t *)ioreq;
write_req->data = task;
const knot_pkt_t *packet;
struct kr_request_qsource_flags flags; /**< See definition above. */
size_t size; /**< query packet size */
+ int32_t stream_id; /**< HTTP/2 stream ID for DoH requests */
} qsource;
struct {
unsigned rtt; /**< Current upstream RTT */
* Consume input packet (may be either first query or answer to query originated from kr_resolve_produce())
*
* @note If the I/O fails, provide an empty or NULL packet, this will make iterator recognize nameserver failure.
- *
+ *
* @param request request state (awaiting input)
* @param src [in] packet source address
* @param packet [in] input packet
* If the CONSUME is returned then dst, type and packet will be filled with
* appropriate values and caller is responsible to send them and receive answer.
* If it returns any other state, then content of the variables is undefined.
- *
+ *
* @param request request state (in PRODUCE state)
* @param dst [out] possible address of the next nameserver
* @param type [out] possible used socket type (SOCK_STREAM, SOCK_DGRAM)