Mercurial > hg > nginx
annotate src/event/quic/ngx_event_quic_socket.c @ 9160:dd5fd5719027
QUIC: do not call shutdown() when handshake is in progress.
Instead, when worker is shutting down and handshake is not yet completed,
connection is terminated immediately.
Previously the callback could be called while QUIC handshake was in progress
and, what's more important, before the init() callback. Now it's postponed
after init().
This change is a preparation to postponing HTTP/3 session creation to init().
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Thu, 21 Sep 2023 19:32:38 +0400 |
parents | 8f7e6d8c061e |
children |
rev | line source |
---|---|
8763 | 1 |
2 /* | |
3 * Copyright (C) Nginx, Inc. | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 #include <ngx_event_quic_connection.h> | |
11 | |
12 | |
13 ngx_int_t | |
14 ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, | |
15 ngx_quic_header_t *pkt) | |
16 { | |
8955
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
17 ngx_quic_socket_t *qsock, *tmp; |
8763 | 18 ngx_quic_client_id_t *cid; |
19 | |
20 /* | |
8971
1e2f4e9c8195
QUIC: reworked migration handling.
Vladimir Homutov <vl@nginx.com>
parents:
8955
diff
changeset
|
21 * qc->path = NULL |
1e2f4e9c8195
QUIC: reworked migration handling.
Vladimir Homutov <vl@nginx.com>
parents:
8955
diff
changeset
|
22 * |
8763 | 23 * qc->nclient_ids = 0 |
24 * qc->nsockets = 0 | |
25 * qc->max_retired_seqnum = 0 | |
26 * qc->client_seqnum = 0 | |
27 */ | |
28 | |
29 ngx_queue_init(&qc->sockets); | |
30 ngx_queue_init(&qc->free_sockets); | |
31 | |
32 ngx_queue_init(&qc->paths); | |
33 ngx_queue_init(&qc->free_paths); | |
34 | |
35 ngx_queue_init(&qc->client_ids); | |
36 ngx_queue_init(&qc->free_client_ids); | |
37 | |
38 qc->tp.original_dcid.len = pkt->odcid.len; | |
39 qc->tp.original_dcid.data = ngx_pstrdup(c->pool, &pkt->odcid); | |
40 if (qc->tp.original_dcid.data == NULL) { | |
9015
a2fbae359828
QUIC: fixed indentation.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8997
diff
changeset
|
41 return NGX_ERROR; |
8763 | 42 } |
43 | |
8955
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
44 /* socket to use for further processing (id auto-generated) */ |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
45 qsock = ngx_quic_create_socket(c, qc); |
8763 | 46 if (qsock == NULL) { |
47 return NGX_ERROR; | |
48 } | |
49 | |
8955
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
50 /* socket is listening at new server id */ |
8763 | 51 if (ngx_quic_listen(c, qc, qsock) != NGX_OK) { |
52 return NGX_ERROR; | |
53 } | |
54 | |
8971
1e2f4e9c8195
QUIC: reworked migration handling.
Vladimir Homutov <vl@nginx.com>
parents:
8955
diff
changeset
|
55 qsock->used = 1; |
1e2f4e9c8195
QUIC: reworked migration handling.
Vladimir Homutov <vl@nginx.com>
parents:
8955
diff
changeset
|
56 |
8763 | 57 qc->tp.initial_scid.len = qsock->sid.len; |
58 qc->tp.initial_scid.data = ngx_pnalloc(c->pool, qsock->sid.len); | |
59 if (qc->tp.initial_scid.data == NULL) { | |
60 goto failed; | |
61 } | |
62 ngx_memcpy(qc->tp.initial_scid.data, qsock->sid.id, qsock->sid.len); | |
63 | |
64 /* for all packets except first, this is set at udp layer */ | |
65 c->udp = &qsock->udp; | |
66 | |
67 /* ngx_quic_get_connection(c) macro is now usable */ | |
68 | |
69 /* we have a client identified by scid */ | |
70 cid = ngx_quic_create_client_id(c, &pkt->scid, 0, NULL); | |
71 if (cid == NULL) { | |
72 goto failed; | |
73 } | |
74 | |
8971
1e2f4e9c8195
QUIC: reworked migration handling.
Vladimir Homutov <vl@nginx.com>
parents:
8955
diff
changeset
|
75 /* path of the first packet is our initial active path */ |
1e2f4e9c8195
QUIC: reworked migration handling.
Vladimir Homutov <vl@nginx.com>
parents:
8955
diff
changeset
|
76 qc->path = ngx_quic_new_path(c, c->sockaddr, c->socklen, cid); |
1e2f4e9c8195
QUIC: reworked migration handling.
Vladimir Homutov <vl@nginx.com>
parents:
8955
diff
changeset
|
77 if (qc->path == NULL) { |
8763 | 78 goto failed; |
79 } | |
80 | |
8971
1e2f4e9c8195
QUIC: reworked migration handling.
Vladimir Homutov <vl@nginx.com>
parents:
8955
diff
changeset
|
81 qc->path->tag = NGX_QUIC_PATH_ACTIVE; |
1e2f4e9c8195
QUIC: reworked migration handling.
Vladimir Homutov <vl@nginx.com>
parents:
8955
diff
changeset
|
82 |
8763 | 83 if (pkt->validated) { |
8971
1e2f4e9c8195
QUIC: reworked migration handling.
Vladimir Homutov <vl@nginx.com>
parents:
8955
diff
changeset
|
84 qc->path->validated = 1; |
8763 | 85 } |
86 | |
8971
1e2f4e9c8195
QUIC: reworked migration handling.
Vladimir Homutov <vl@nginx.com>
parents:
8955
diff
changeset
|
87 ngx_quic_path_dbg(c, "set active", qc->path); |
8763 | 88 |
8955
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
89 tmp = ngx_pcalloc(c->pool, sizeof(ngx_quic_socket_t)); |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
90 if (tmp == NULL) { |
8763 | 91 goto failed; |
92 } | |
93 | |
8955
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
94 tmp->sid.seqnum = NGX_QUIC_UNSET_PN; /* temporary socket */ |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
95 |
9153
8f7e6d8c061e
QUIC: use last client dcid to receive initial packets.
Roman Arutyunyan <arut@nginx.com>
parents:
9144
diff
changeset
|
96 ngx_memcpy(tmp->sid.id, pkt->dcid.data, pkt->dcid.len); |
8f7e6d8c061e
QUIC: use last client dcid to receive initial packets.
Roman Arutyunyan <arut@nginx.com>
parents:
9144
diff
changeset
|
97 tmp->sid.len = pkt->dcid.len; |
8955
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
98 |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
99 if (ngx_quic_listen(c, qc, tmp) != NGX_OK) { |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
100 goto failed; |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
101 } |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
102 |
8763 | 103 return NGX_OK; |
104 | |
105 failed: | |
106 | |
107 ngx_rbtree_delete(&c->listening->rbtree, &qsock->udp.node); | |
108 c->udp = NULL; | |
109 | |
110 return NGX_ERROR; | |
111 } | |
112 | |
113 | |
114 ngx_quic_socket_t * | |
8955
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
115 ngx_quic_create_socket(ngx_connection_t *c, ngx_quic_connection_t *qc) |
8763 | 116 { |
117 ngx_queue_t *q; | |
118 ngx_quic_socket_t *sock; | |
119 | |
120 if (!ngx_queue_empty(&qc->free_sockets)) { | |
121 | |
122 q = ngx_queue_head(&qc->free_sockets); | |
123 sock = ngx_queue_data(q, ngx_quic_socket_t, queue); | |
124 | |
125 ngx_queue_remove(&sock->queue); | |
126 | |
127 ngx_memzero(sock, sizeof(ngx_quic_socket_t)); | |
128 | |
129 } else { | |
130 | |
131 sock = ngx_pcalloc(c->pool, sizeof(ngx_quic_socket_t)); | |
132 if (sock == NULL) { | |
133 return NULL; | |
134 } | |
135 } | |
136 | |
8955
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
137 sock->sid.len = NGX_QUIC_SERVER_CID_LEN; |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
138 if (ngx_quic_create_server_id(c, sock->sid.id) != NGX_OK) { |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
139 return NULL; |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
140 } |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
141 |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
142 sock->sid.seqnum = qc->server_seqnum++; |
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
143 |
8763 | 144 return sock; |
145 } | |
146 | |
147 | |
148 void | |
149 ngx_quic_close_socket(ngx_connection_t *c, ngx_quic_socket_t *qsock) | |
150 { | |
151 ngx_quic_connection_t *qc; | |
152 | |
153 qc = ngx_quic_get_connection(c); | |
154 | |
155 ngx_queue_remove(&qsock->queue); | |
156 ngx_queue_insert_head(&qc->free_sockets, &qsock->queue); | |
157 | |
158 ngx_rbtree_delete(&c->listening->rbtree, &qsock->udp.node); | |
159 qc->nsockets--; | |
160 | |
161 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
8997
fab36e4abf83
QUIC: got rid of hash symbol in backup and logging.
Vladimir Homutov <vl@nginx.com>
parents:
8971
diff
changeset
|
162 "quic socket seq:%L closed nsock:%ui", |
8763 | 163 (int64_t) qsock->sid.seqnum, qc->nsockets); |
164 } | |
165 | |
166 | |
167 ngx_int_t | |
168 ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc, | |
169 ngx_quic_socket_t *qsock) | |
170 { | |
171 ngx_str_t id; | |
172 ngx_quic_server_id_t *sid; | |
173 | |
174 sid = &qsock->sid; | |
175 | |
176 id.data = sid->id; | |
177 id.len = sid->len; | |
178 | |
9017
c2f5d79cde64
QUIC: separate UDP framework for QUIC.
Roman Arutyunyan <arut@nginx.com>
parents:
9015
diff
changeset
|
179 qsock->udp.connection = c; |
c2f5d79cde64
QUIC: separate UDP framework for QUIC.
Roman Arutyunyan <arut@nginx.com>
parents:
9015
diff
changeset
|
180 qsock->udp.node.key = ngx_crc32_long(id.data, id.len); |
9107
adcc6d8acfd4
Common tree insert function for QUIC and UDP connections.
Roman Arutyunyan <arut@nginx.com>
parents:
9017
diff
changeset
|
181 qsock->udp.key = id; |
9017
c2f5d79cde64
QUIC: separate UDP framework for QUIC.
Roman Arutyunyan <arut@nginx.com>
parents:
9015
diff
changeset
|
182 |
c2f5d79cde64
QUIC: separate UDP framework for QUIC.
Roman Arutyunyan <arut@nginx.com>
parents:
9015
diff
changeset
|
183 ngx_rbtree_insert(&c->listening->rbtree, &qsock->udp.node); |
8763 | 184 |
185 ngx_queue_insert_tail(&qc->sockets, &qsock->queue); | |
186 | |
187 qc->nsockets++; | |
188 qsock->quic = qc; | |
189 | |
190 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
8997
fab36e4abf83
QUIC: got rid of hash symbol in backup and logging.
Vladimir Homutov <vl@nginx.com>
parents:
8971
diff
changeset
|
191 "quic socket seq:%L listening at sid:%xV nsock:%ui", |
8955
32daba3aabb2
QUIC: got rid of ngx_quic_create_temp_socket().
Vladimir Homutov <vl@nginx.com>
parents:
8940
diff
changeset
|
192 (int64_t) sid->seqnum, &id, qc->nsockets); |
8763 | 193 |
194 return NGX_OK; | |
195 } | |
196 | |
197 | |
198 void | |
199 ngx_quic_close_sockets(ngx_connection_t *c) | |
200 { | |
201 ngx_queue_t *q; | |
202 ngx_quic_socket_t *qsock; | |
203 ngx_quic_connection_t *qc; | |
204 | |
205 qc = ngx_quic_get_connection(c); | |
206 | |
207 while (!ngx_queue_empty(&qc->sockets)) { | |
208 q = ngx_queue_head(&qc->sockets); | |
209 qsock = ngx_queue_data(q, ngx_quic_socket_t, queue); | |
210 | |
211 ngx_quic_close_socket(c, qsock); | |
212 } | |
213 } | |
214 | |
215 | |
216 ngx_quic_socket_t * | |
217 ngx_quic_find_socket(ngx_connection_t *c, uint64_t seqnum) | |
218 { | |
219 ngx_queue_t *q; | |
220 ngx_quic_socket_t *qsock; | |
221 ngx_quic_connection_t *qc; | |
222 | |
223 qc = ngx_quic_get_connection(c); | |
224 | |
225 for (q = ngx_queue_head(&qc->sockets); | |
226 q != ngx_queue_sentinel(&qc->sockets); | |
227 q = ngx_queue_next(q)) | |
228 { | |
229 qsock = ngx_queue_data(q, ngx_quic_socket_t, queue); | |
230 | |
231 if (qsock->sid.seqnum == seqnum) { | |
232 return qsock; | |
233 } | |
234 } | |
235 | |
236 return NULL; | |
237 } |