|
21 | 21 | *============================================================================= |
22 | 22 | * |
23 | 23 | * A simple dtls server example with configurable threadpool, for |
24 | | - * instructional/learning purposes. Utilizes DTLS 1.2. |
| 24 | + * instructional/learning purposes. Utilizes DTLS 1.2. Please note that if |
| 25 | + * multiple client hellos arrive at the same time, the server might drop some of |
| 26 | + * them. A production-ready server needs a more sophisticated mechanism to |
| 27 | + * multiplex packets from different clients to the same port. |
25 | 28 | */ |
26 | 29 |
|
27 | 30 | #include <wolfssl/options.h> |
@@ -174,57 +177,47 @@ main(int argc, |
174 | 177 | continue; |
175 | 178 | } |
176 | 179 |
|
| 180 | + ret = recvfrom(listenfd, NULL, 0, MSG_PEEK, |
| 181 | + (struct sockaddr *)&cliaddr, &cliLen); |
| 182 | + if (ret < 0) |
| 183 | + continue; |
| 184 | + |
| 185 | + printf("Received a packet from %s:%d\n", |
| 186 | + inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)); |
| 187 | + |
177 | 188 | memset(&args[i], 0, sizeof(thread_args_t)); |
| 189 | + args[i].activefd = listenfd; |
| 190 | + listenfd = new_udp_listen_socket(); |
| 191 | + /* Avoid future packets from other peers to be received over |
| 192 | + * args[i].activefd. Please note that packets from other clients |
| 193 | + * already received might be returned from future invocations of |
| 194 | + * recvfrom()/read(). The args[i].ssl object will discard those packets |
| 195 | + * that don't match the set DTLS peer. */ |
| 196 | + ret = connect(args[i].activefd, (const struct sockaddr *)&cliaddr, cliLen); |
| 197 | + if (ret != 0) { |
| 198 | + printf("error: connect returned: %d\n", ret); |
| 199 | + break; |
| 200 | + } |
178 | 201 |
|
179 | 202 | args[i].ssl = wolfSSL_new(ctx); |
180 | 203 | if (args[i].ssl == NULL) { |
181 | 204 | printf("error: wolfSSL_new returned null\n"); |
182 | 205 | break; |
183 | 206 | } |
184 | 207 |
|
185 | | - /* set the session ssl to client connection port */ |
186 | | - ret = wolfSSL_set_fd(args[i].ssl, listenfd); |
| 208 | + ret = wolfSSL_set_fd(args[i].ssl, args[i].activefd); |
187 | 209 | if (ret != SSL_SUCCESS) { |
188 | | - printf("error: wolfSSL_set_fd returned %d\n", ret); |
| 210 | + printf("error: wolfSSL_set_fd: %d\n", ret); |
189 | 211 | break; |
190 | 212 | } |
191 | 213 |
|
192 | | - ret = wolfSSL_accept(args[i].ssl); |
193 | | - if (ret != SSL_SUCCESS) { |
194 | | - printf("error: wolfSSL_accept returned %d\n", ret); |
195 | | - break; |
196 | | - } |
197 | | - |
198 | | - ret = wolfSSL_dtls_get_peer(args[i].ssl, &cliaddr, &cliLen); |
| 214 | + ret = wolfSSL_dtls_set_peer(args[i].ssl, &cliaddr, cliLen); |
199 | 215 | if (ret != WOLFSSL_SUCCESS) { |
200 | | - printf("error: wolfSSL_dtls_get_peer failed\n"); |
| 216 | + printf("error: wolfSSL_dtls_set_peer: %d\n", ret); |
201 | 217 | break; |
202 | 218 | } |
203 | 219 |
|
204 | 220 | args[i].peer_port = ntohs(cliaddr.sin_port); |
205 | | - |
206 | | - printf("info: new dtls session: %p, %d\n", (void*) args[i].ssl, |
207 | | - args[i].peer_port); |
208 | | - |
209 | | - /* Open new UDP socket. */ |
210 | | - args[i].activefd = new_udp_listen_socket(); |
211 | | - if (args[i].activefd <= 0 ) { |
212 | | - break; |
213 | | - } |
214 | | - |
215 | | - ret = connect(args[i].activefd, (const struct sockaddr *)&cliaddr, |
216 | | - cliLen); |
217 | | - if (ret != 0) { |
218 | | - printf("error: connect returned: %d\n", ret); |
219 | | - break; |
220 | | - } |
221 | | - |
222 | | - ret = wolfSSL_set_dtls_fd_connected(args[i].ssl, args[i].activefd); |
223 | | - if (ret != SSL_SUCCESS) { |
224 | | - printf("error: wolfSSL_set_dtls_fd_connected: %d\n", ret); |
225 | | - break; |
226 | | - } |
227 | | - |
228 | 221 | ret = pthread_create(&threads[i], NULL, server_work, &args[i]); |
229 | 222 |
|
230 | 223 | if (ret == 0 ) { |
@@ -319,6 +312,19 @@ server_work(void * args) |
319 | 312 | int n_bytes = 0; |
320 | 313 | char recv_msg[MSGLEN]; |
321 | 314 | char send_msg[MSGLEN]; |
| 315 | + int ret; |
| 316 | + |
| 317 | + ret = wolfSSL_accept(thread_args->ssl); |
| 318 | + if (ret != SSL_SUCCESS) |
| 319 | + { |
| 320 | + printf("error: wolfSSL_accept returned %d\n", ret); |
| 321 | + pthread_exit(NULL); |
| 322 | + /* we should never reach here */ |
| 323 | + return NULL; |
| 324 | + } |
| 325 | + |
| 326 | + printf("info: new dtls session: %p, %d\n", (void *)thread_args->ssl, |
| 327 | + thread_args->peer_port); |
322 | 328 |
|
323 | 329 | for (size_t i = 0; i < 4; ++i) { |
324 | 330 | if (stop_server) { |
@@ -374,14 +380,21 @@ server_work(void * args) |
374 | 380 | static void |
375 | 381 | safer_shutdown(thread_args_t * args) |
376 | 382 | { |
| 383 | + int ret; |
| 384 | + |
377 | 385 | if (args == NULL) { |
378 | 386 | printf("error: safer_shutdown with null args\n"); |
379 | 387 | return; |
380 | 388 | } |
381 | 389 |
|
382 | 390 | if (args->ssl != NULL) { |
383 | 391 | printf("info: closed dtls session: %p\n", (void*) args->ssl); |
384 | | - wolfSSL_shutdown(args->ssl); |
| 392 | + ret = wolfSSL_shutdown(args->ssl); |
| 393 | + |
| 394 | + /* bidirectional shutdown */ |
| 395 | + if (ret != WOLFSSL_SUCCESS) |
| 396 | + ret = wolfSSL_shutdown(args->ssl); |
| 397 | + |
385 | 398 | wolfSSL_free(args->ssl); |
386 | 399 | args->ssl = NULL; |
387 | 400 | } |
|
0 commit comments