summaryrefslogtreecommitdiffstats
path: root/daemon/session.h
blob: 1f95ac5b6888ea61c214f373b9894fe76aaf82cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*  Copyright (C) CZ.NIC, z.s.p.o. <knot-resolver@labs.nic.cz>
 *  SPDX-License-Identifier: GPL-3.0-or-later
 */

#pragma once

#include <libknot/packet/pkt.h>

#include <stdbool.h>
#include <uv.h>
#include "lib/defines.h"

struct qr_task;
struct worker_ctx;
struct session;
struct io_comm_data;
struct proxy_result;

struct session_flags {
	bool outgoing : 1;      /**< True: to upstream; false: from a client. */
	bool throttled : 1;     /**< True: data reading from peer is temporarily stopped. */
	bool has_tls : 1;       /**< True: given session uses TLS. */
	bool has_http : 1;      /**< True: given session uses HTTP. */
	bool connected : 1;     /**< True: TCP connection is established. */
	bool no_proxy : 1;      /**< True: TCP has gotten some data - PROXYv2 header
	                         * disallowed. Proxy headers are only expected at
	                         * the very start of a stream. */
	bool closing : 1;       /**< True: session close sequence is in progress. */
	bool wirebuf_error : 1; /**< True: last operation with wirebuf ended up with an error. */
};

/** Allocate new session for a libuv handle.
 * If handle->type isn't UV_TCP, has_* parameters will be ignored. */
struct session *session_new(uv_handle_t *handle, bool has_tls, bool has_http);
/** Clear and free given session. */
void session_free(struct session *session);
/** Clear session. */
void session_clear(struct session *session);
/** Close session. */
void session_close(struct session *session);
/** Start reading from underlying libuv IO handle. */
int session_start_read(struct session *session);
/** Stop reading from underlying libuv IO handle. */
int session_stop_read(struct session *session);

/** List of tasks been waiting for IO. */
/** Check if list is empty. */
bool session_waitinglist_is_empty(const struct session *session);
/** Add task to the end of the list. */
int session_waitinglist_push(struct session *session, struct qr_task *task);
/** Get the first element. */
struct qr_task *session_waitinglist_get(const struct session *session);
/** Get the first element and remove it from the list. */
struct qr_task *session_waitinglist_pop(struct session *session, bool deref);
/** Get the list length. */
size_t session_waitinglist_get_len(const struct session *session);
/** Retry resolution for each task in the list. */
void session_waitinglist_retry(struct session *session, bool increase_timeout_cnt);
/** Finalize all tasks in the list. */
void session_waitinglist_finalize(struct session *session, int status);

/** PROXYv2 data. */
/** Creates zero-initialized PROXYv2 data for the session. Should only be called
 * once per session. */
struct proxy_result *session_proxy_create(struct session *session);
/** Gets the session's PROXYv2 data, if it exists. If it does not, returns `NULL`. */
struct proxy_result *session_proxy_get(struct session *session);

/** List of tasks associated with session. */
/** Check if list is empty. */
bool session_tasklist_is_empty(const struct session *session);
/** Get the first element. */
struct qr_task *session_tasklist_get_first(struct session *session);
/** Get the first element and remove it from the list. */
struct qr_task *session_tasklist_del_first(struct session *session, bool deref);
/** Get the list length. */
size_t session_tasklist_get_len(const struct session *session);
/** Add task to the list. */
int session_tasklist_add(struct session *session, struct qr_task *task);
/** Remove task from the list. */
int session_tasklist_del(struct session *session, struct qr_task *task);
/** Remove task with given msg_id, session_flags(session)->outgoing must be true. */
struct qr_task* session_tasklist_del_msgid(const struct session *session, uint16_t msg_id);
/** Find task with given msg_id */
struct qr_task* session_tasklist_find_msgid(const struct session *session, uint16_t msg_id);
/** Finalize all tasks in the list. */
void session_tasklist_finalize(struct session *session, int status);
/** Finalize all expired tasks in the list. */
int session_tasklist_finalize_expired(struct session *session);

/** Both of task lists (associated & waiting). */
/** Check if empty. */
bool session_is_empty(const struct session *session);
/** Penalize this server if the session hasn't been useful (and is outgoing). */
void session_tcp_penalize(struct session *session);

/** Get pointer to session flags */
struct session_flags *session_flags(struct session *session);
/** Get pointer to peer address. */
struct sockaddr *session_get_peer(struct session *session);
/** Get pointer to sockname (address of our end, not meaningful for UDP downstream). */
struct sockaddr *session_get_sockname(struct session *session);
/** Get pointer to server-side tls-related data. */
struct tls_ctx *session_tls_get_server_ctx(const struct session *session);
/** Set pointer to server-side tls-related data. */
void session_tls_set_server_ctx(struct session *session, struct tls_ctx *ctx);
/** Get pointer to client-side tls-related data. */
struct tls_client_ctx *session_tls_get_client_ctx(const struct session *session);
/** Set pointer to client-side tls-related data. */
void session_tls_set_client_ctx(struct session *session, struct tls_client_ctx *ctx);
/** Get pointer to that part of tls-related data which has common structure for
 *  server and client. */
struct tls_common_ctx *session_tls_get_common_ctx(const struct session *session);

#if ENABLE_DOH2
/** Get pointer to server-side http-related data. */
struct http_ctx *session_http_get_server_ctx(const struct session *session);
/** Set pointer to server-side http-related data. */
void session_http_set_server_ctx(struct session *session, struct http_ctx *ctx);
#endif

/** Get pointer to underlying libuv handle for IO operations. */
KR_EXPORT uv_handle_t *session_get_handle(struct session *session);
struct session *session_get(uv_handle_t *h);

/** Start session timer. */
int session_timer_start(struct session *session, uv_timer_cb cb,
			uint64_t timeout, uint64_t repeat);
/** Restart session timer without changing it parameters. */
int session_timer_restart(struct session *session);
/** Stop session timer. */
int session_timer_stop(struct session *session);

/** Get pointer to the beginning of session wirebuffer. */
uint8_t *session_wirebuf_get_start(struct session *session);
/** Get size of session wirebuffer. */
size_t session_wirebuf_get_size(struct session *session);
/** Get pointer to the beginning of free space in session wirebuffer. */
uint8_t *session_wirebuf_get_free_start(struct session *session);
/** Get amount of free space in session wirebuffer. */
size_t session_wirebuf_get_free_size(struct session *session);
/** Discard all data in session wirebuffer. */
void session_wirebuf_discard(struct session *session);
/** Move all data to the beginning of the buffer. */
void session_wirebuf_compress(struct session *session);
int session_wirebuf_process(struct session *session, struct io_comm_data *comm);
ssize_t session_wirebuf_consume(struct session *session,
				const uint8_t *data, ssize_t len);
/** Trims `len` bytes from the start of the session's wire buffer.
 * If this operation makes the buffer's end appear before the start, it gets
 * nudged to the same position as the start. */
ssize_t session_wirebuf_trim(struct session *session, ssize_t len);
/** poison session structure with ASAN. */
void session_poison(struct session *session);
/** unpoison session structure with ASAN. */
void session_unpoison(struct session *session);

knot_pkt_t *session_produce_packet(struct session *session, knot_mm_t *mm);
int session_discard_packet(struct session *session, const knot_pkt_t *pkt);

void session_kill_ioreq(struct session *session, struct qr_task *task);
/** Update timestamp */
void session_touch(struct session *session);
/** Returns either creation time or time of last IO activity if any occurs. */
/* Used for TCP timeout calculation. */
uint64_t session_last_activity(struct session *session);