1 /*
2 * Copyright (C) 2010-2025 Red Hat, Inc. All rights reserved.
3 *
4 * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
5 * Federico Simoncelli <fsimon@kronosnet.org>
6 *
7 * This software licensed under LGPL-2.0+
8 */
9
10 #include "config.h"
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <pthread.h>
17 #include <math.h>
18 #include <sys/time.h>
19 #include <sys/resource.h>
20
21 #include "internals.h"
22 #include "crypto.h"
23 #include "links.h"
24 #include "compress.h"
25 #include "compat.h"
26 #include "common.h"
27 #include "threads_common.h"
28 #include "threads_heartbeat.h"
29 #include "threads_pmtud.h"
30 #include "threads_dsthandler.h"
31 #include "threads_rx.h"
32 #include "threads_tx.h"
33 #include "transports.h"
34 #include "transport_common.h"
35 #include "logging.h"
36
37 static int _init_locks(knet_handle_t knet_h)
38 {
39 int savederrno = 0;
40
41 savederrno = pthread_rwlock_init(&knet_h->global_rwlock, NULL);
42 if (savederrno) {
43 log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize list rwlock: %s",
44 strerror(savederrno));
45 goto exit_fail;
46 }
47
48 savederrno = pthread_mutex_init(&knet_h->handle_stats_mutex, NULL);
49 if (savederrno) {
50 log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize handle stats mutex: %s",
51 strerror(savederrno));
52 goto exit_fail;
53 }
54
55 savederrno = pthread_mutex_init(&knet_h->threads_status_mutex, NULL);
56 if (savederrno) {
57 log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize threads status mutex: %s",
58 strerror(savederrno));
59 goto exit_fail;
60 }
61
62 savederrno = pthread_mutex_init(&knet_h->pmtud_mutex, NULL);
63 if (savederrno) {
64 log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize pmtud mutex: %s",
65 strerror(savederrno));
66 goto exit_fail;
67 }
68
69 savederrno = pthread_mutex_init(&knet_h->kmtu_mutex, NULL);
70 if (savederrno) {
71 log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize kernel_mtu mutex: %s",
72 strerror(savederrno));
73 goto exit_fail;
74 }
75
76 savederrno = pthread_cond_init(&knet_h->pmtud_cond, NULL);
77 if (savederrno) {
78 log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize pmtud conditional mutex: %s",
79 strerror(savederrno));
80 goto exit_fail;
81 }
82
83 savederrno = pthread_mutex_init(&knet_h->hb_mutex, NULL);
84 if (savederrno) {
85 log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize hb_thread mutex: %s",
86 strerror(savederrno));
87 goto exit_fail;
88 }
89
90 savederrno = pthread_mutex_init(&knet_h->tx_mutex, NULL);
91 if (savederrno) {
92 log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize tx_thread mutex: %s",
93 strerror(savederrno));
94 goto exit_fail;
95 }
96
97 savederrno = pthread_mutex_init(&knet_h->backoff_mutex, NULL);
98 if (savederrno) {
99 log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize pong timeout backoff mutex: %s",
100 strerror(savederrno));
101 goto exit_fail;
102 }
103
104 savederrno = pthread_mutex_init(&knet_h->tx_seq_num_mutex, NULL);
105 if (savederrno) {
106 log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize tx_seq_num_mutex mutex: %s",
107 strerror(savederrno));
108 goto exit_fail;
109 }
110
111 return 0;
112
113 exit_fail:
114 errno = savederrno;
115 return -1;
116 }
117
118 static void _destroy_locks(knet_handle_t knet_h)
119 {
120 pthread_rwlock_destroy(&knet_h->global_rwlock);
121 pthread_mutex_destroy(&knet_h->pmtud_mutex);
122 pthread_mutex_destroy(&knet_h->kmtu_mutex);
123 pthread_cond_destroy(&knet_h->pmtud_cond);
124 pthread_mutex_destroy(&knet_h->hb_mutex);
125 pthread_mutex_destroy(&knet_h->tx_mutex);
126 pthread_mutex_destroy(&knet_h->backoff_mutex);
127 pthread_mutex_destroy(&knet_h->tx_seq_num_mutex);
128 pthread_mutex_destroy(&knet_h->threads_status_mutex);
129 pthread_mutex_destroy(&knet_h->handle_stats_mutex);
130 }
131
132 static int _init_socks(knet_handle_t knet_h)
133 {
134 int savederrno = 0;
135
136 if (_init_socketpair(knet_h, knet_h->dstsockfd)) {
137 savederrno = errno;
138 log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize internal dstsockpair: %s",
139 strerror(savederrno));
140 goto exit_fail;
141 }
142
143 return 0;
144
145 exit_fail:
146 errno = savederrno;
147 return -1;
148 }
149
150 static void _close_socks(knet_handle_t knet_h)
151 {
152 _close_socketpair(knet_h, knet_h->dstsockfd);
153 }
154
155 static int _init_buffers(knet_handle_t knet_h)
156 {
157 int savederrno = 0;
158 unsigned int i;
159 size_t bufsize;
160
161 for (i = 0; i < PCKT_FRAG_MAX; i++) {
162 bufsize = ceil((float)KNET_MAX_PACKET_SIZE / (i + 1)) + KNET_HEADER_ALL_SIZE;
163 knet_h->send_to_links_buf[i] = malloc(bufsize);
164 if (!knet_h->send_to_links_buf[i]) {
165 savederrno = errno;
166 log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory datafd to link buffer: %s",
167 strerror(savederrno));
168 goto exit_fail;
169 }
170 memset(knet_h->send_to_links_buf[i], 0, bufsize);
171 }
172
173 for (i = 0; i < PCKT_RX_BUFS; i++) {
174 knet_h->recv_from_links_buf[i] = malloc(KNET_DATABUFSIZE);
175 if (!knet_h->recv_from_links_buf[i]) {
176 savederrno = errno;
177 log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for link to datafd buffer: %s",
178 strerror(savederrno));
179 goto exit_fail;
180 }
181 memset(knet_h->recv_from_links_buf[i], 0, KNET_DATABUFSIZE);
182 }
183
184 knet_h->recv_from_sock_buf = malloc(KNET_DATABUFSIZE);
185 if (!knet_h->recv_from_sock_buf) {
186 savederrno = errno;
187 log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for app to datafd buffer: %s",
188 strerror(savederrno));
189 goto exit_fail;
190 }
191 memset(knet_h->recv_from_sock_buf, 0, KNET_DATABUFSIZE);
192
193 knet_h->pingbuf = malloc(KNET_HEADER_PING_SIZE);
194 if (!knet_h->pingbuf) {
195 savederrno = errno;
196 log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for hearbeat buffer: %s",
197 strerror(savederrno));
198 goto exit_fail;
199 }
200 memset(knet_h->pingbuf, 0, KNET_HEADER_PING_SIZE);
201
202 knet_h->pmtudbuf = malloc(KNET_PMTUD_SIZE_V6 + KNET_HEADER_ALL_SIZE);
203 if (!knet_h->pmtudbuf) {
204 savederrno = errno;
205 log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for pmtud buffer: %s",
206 strerror(savederrno));
207 goto exit_fail;
208 }
209 memset(knet_h->pmtudbuf, 0, KNET_PMTUD_SIZE_V6 + KNET_HEADER_ALL_SIZE);
210
211 for (i = 0; i < PCKT_FRAG_MAX; i++) {
212 bufsize = ceil((float)KNET_MAX_PACKET_SIZE / (i + 1)) + KNET_HEADER_ALL_SIZE + KNET_DATABUFSIZE_CRYPT_PAD;
213 knet_h->send_to_links_buf_crypt[i] = malloc(bufsize);
214 if (!knet_h->send_to_links_buf_crypt[i]) {
215 savederrno = errno;
216 log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for crypto datafd to link buffer: %s",
217 strerror(savederrno));
218 goto exit_fail;
219 }
220 memset(knet_h->send_to_links_buf_crypt[i], 0, bufsize);
221 }
222
223 knet_h->recv_from_links_buf_decrypt = malloc(KNET_DATABUFSIZE_CRYPT);
224 if (!knet_h->recv_from_links_buf_decrypt) {
225 savederrno = errno;
226 log_err(knet_h, KNET_SUB_CRYPTO, "Unable to allocate memory for crypto link to datafd buffer: %s",
227 strerror(savederrno));
228 goto exit_fail;
229 }
230 memset(knet_h->recv_from_links_buf_decrypt, 0, KNET_DATABUFSIZE_CRYPT);
231
232 knet_h->recv_from_links_buf_crypt = malloc(KNET_DATABUFSIZE_CRYPT);
233 if (!knet_h->recv_from_links_buf_crypt) {
234 savederrno = errno;
235 log_err(knet_h, KNET_SUB_CRYPTO, "Unable to allocate memory for crypto link to datafd buffer: %s",
236 strerror(savederrno));
237 goto exit_fail;
238 }
239 memset(knet_h->recv_from_links_buf_crypt, 0, KNET_DATABUFSIZE_CRYPT);
240
241 knet_h->pingbuf_crypt = malloc(KNET_DATABUFSIZE_CRYPT);
242 if (!knet_h->pingbuf_crypt) {
243 savederrno = errno;
244 log_err(knet_h, KNET_SUB_CRYPTO, "Unable to allocate memory for crypto hearbeat buffer: %s",
245 strerror(savederrno));
246 goto exit_fail;
247 }
248 memset(knet_h->pingbuf_crypt, 0, KNET_DATABUFSIZE_CRYPT);
249
250 knet_h->pmtudbuf_crypt = malloc(KNET_DATABUFSIZE_CRYPT);
251 if (!knet_h->pmtudbuf_crypt) {
252 savederrno = errno;
253 log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for crypto pmtud buffer: %s",
254 strerror(savederrno));
255 goto exit_fail;
256 }
257 memset(knet_h->pmtudbuf_crypt, 0, KNET_DATABUFSIZE_CRYPT);
258
259 knet_h->recv_from_links_buf_decompress = malloc(KNET_DATABUFSIZE_COMPRESS);
260 if (!knet_h->recv_from_links_buf_decompress) {
261 savederrno = errno;
262 log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for decompress buffer: %s",
263 strerror(savederrno));
264 goto exit_fail;
265 }
266 memset(knet_h->recv_from_links_buf_decompress, 0, KNET_DATABUFSIZE_COMPRESS);
267
268 knet_h->send_to_links_buf_compress = malloc(KNET_DATABUFSIZE_COMPRESS);
269 if (!knet_h->send_to_links_buf_compress) {
270 savederrno = errno;
271 log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for compress buffer: %s",
272 strerror(savederrno));
273 goto exit_fail;
274 }
275 memset(knet_h->send_to_links_buf_compress, 0, KNET_DATABUFSIZE_COMPRESS);
276
277 memset(knet_h->knet_transport_fd_tracker, 0, sizeof(knet_h->knet_transport_fd_tracker));
278 for (i = 0; i < KNET_MAX_FDS; i++) {
279 knet_h->knet_transport_fd_tracker[i].transport = KNET_MAX_TRANSPORTS;
280 }
281
282 return 0;
283
284 exit_fail:
285 errno = savederrno;
286 return -1;
287 }
288
289 static void _destroy_buffers(knet_handle_t knet_h)
290 {
291 unsigned int i;
292
293 for (i = 0; i < PCKT_FRAG_MAX; i++) {
294 free(knet_h->send_to_links_buf[i]);
295 free(knet_h->send_to_links_buf_crypt[i]);
296 }
297
298 for (i = 0; i < PCKT_RX_BUFS; i++) {
299 free(knet_h->recv_from_links_buf[i]);
300 }
301
302 free(knet_h->recv_from_links_buf_decompress);
303 free(knet_h->send_to_links_buf_compress);
304 free(knet_h->recv_from_sock_buf);
305 free(knet_h->recv_from_links_buf_decrypt);
306 free(knet_h->recv_from_links_buf_crypt);
307 free(knet_h->pingbuf);
308 free(knet_h->pingbuf_crypt);
309 free(knet_h->pmtudbuf);
310 free(knet_h->pmtudbuf_crypt);
311 }
312
313 static int _init_epolls(knet_handle_t knet_h)
314 {
315 struct epoll_event ev;
316 int savederrno = 0;
317
318 /*
319 * even if the kernel does dynamic allocation with epoll_ctl
320 * we need to reserve one extra for host to host communication
321 */
322 knet_h->send_to_links_epollfd = epoll_create(KNET_EPOLL_MAX_EVENTS + 1);
323 if (knet_h->send_to_links_epollfd < 0) {
324 savederrno = errno;
325 log_err(knet_h, KNET_SUB_HANDLE, "Unable to create epoll datafd to link fd: %s",
326 strerror(savederrno));
327 goto exit_fail;
328 }
329
330 knet_h->recv_from_links_epollfd = epoll_create(KNET_EPOLL_MAX_EVENTS);
331 if (knet_h->recv_from_links_epollfd < 0) {
332 savederrno = errno;
333 log_err(knet_h, KNET_SUB_HANDLE, "Unable to create epoll link to datafd fd: %s",
334 strerror(savederrno));
335 goto exit_fail;
336 }
337
338 knet_h->dst_link_handler_epollfd = epoll_create(KNET_EPOLL_MAX_EVENTS);
339 if (knet_h->dst_link_handler_epollfd < 0) {
340 savederrno = errno;
341 log_err(knet_h, KNET_SUB_HANDLE, "Unable to create epoll dst cache fd: %s",
342 strerror(savederrno));
343 goto exit_fail;
344 }
345
346 if (_fdset_cloexec(knet_h->send_to_links_epollfd)) {
347 savederrno = errno;
348 log_err(knet_h, KNET_SUB_HANDLE, "Unable to set CLOEXEC on datafd to link epoll fd: %s",
349 strerror(savederrno));
350 goto exit_fail;
351 }
352
353 if (_fdset_cloexec(knet_h->recv_from_links_epollfd)) {
354 savederrno = errno;
355 log_err(knet_h, KNET_SUB_HANDLE, "Unable to set CLOEXEC on link to datafd epoll fd: %s",
356 strerror(savederrno));
357 goto exit_fail;
358 }
359
360 if (_fdset_cloexec(knet_h->dst_link_handler_epollfd)) {
361 savederrno = errno;
362 log_err(knet_h, KNET_SUB_HANDLE, "Unable to set CLOEXEC on dst cache epoll fd: %s",
363 strerror(savederrno));
364 goto exit_fail;
365 }
366
367 memset(&ev, 0, sizeof(struct epoll_event));
368 ev.events = EPOLLIN;
369 ev.data.fd = knet_h->dstsockfd[0];
370
371 if (epoll_ctl(knet_h->dst_link_handler_epollfd,
372 EPOLL_CTL_ADD, knet_h->dstsockfd[0], &ev)) {
373 savederrno = errno;
374 log_err(knet_h, KNET_SUB_HANDLE, "Unable to add dstsockfd[0] to epoll pool: %s",
375 strerror(savederrno));
376 goto exit_fail;
377 }
378
379 return 0;
380
381 exit_fail:
382 errno = savederrno;
383 return -1;
384 }
385
386 static void _close_epolls(knet_handle_t knet_h)
387 {
388 struct epoll_event ev;
389 int i;
390
391 memset(&ev, 0, sizeof(struct epoll_event));
392
393 for (i = 0; i < KNET_DATAFD_MAX; i++) {
394 if (knet_h->sockfd[i].in_use) {
395 epoll_ctl(knet_h->send_to_links_epollfd, EPOLL_CTL_DEL, knet_h->sockfd[i].sockfd[knet_h->sockfd[i].is_created], &ev);
396 if (knet_h->sockfd[i].sockfd[knet_h->sockfd[i].is_created]) {
397 _close_socketpair(knet_h, knet_h->sockfd[i].sockfd);
398 }
399 }
400 }
401
402 epoll_ctl(knet_h->dst_link_handler_epollfd, EPOLL_CTL_DEL, knet_h->dstsockfd[0], &ev);
403 close(knet_h->send_to_links_epollfd);
404 close(knet_h->recv_from_links_epollfd);
405 close(knet_h->dst_link_handler_epollfd);
406 }
407
408 static int _start_threads(knet_handle_t knet_h)
409 {
410 int savederrno = 0;
411 pthread_attr_t attr;
412
413 set_thread_status(knet_h, KNET_THREAD_PMTUD, KNET_THREAD_REGISTERED);
414
415 savederrno = pthread_attr_init(&attr);
416 if (savederrno) {
417 log_err(knet_h, KNET_SUB_HANDLE, "Unable to init pthread attributes: %s",
418 strerror(savederrno));
419 goto exit_fail;
420 }
421 savederrno = pthread_attr_setstacksize(&attr, KNET_THREAD_STACK_SIZE);
422 if (savederrno) {
423 log_err(knet_h, KNET_SUB_HANDLE, "Unable to set stack size attribute: %s",
424 strerror(savederrno));
425 goto exit_fail;
426 }
427
428 savederrno = pthread_create(&knet_h->pmtud_link_handler_thread, &attr,
429 _handle_pmtud_link_thread, (void *) knet_h);
430 if (savederrno) {
431 log_err(knet_h, KNET_SUB_HANDLE, "Unable to start pmtud link thread: %s",
432 strerror(savederrno));
433 goto exit_fail;
434 }
435
436 set_thread_status(knet_h, KNET_THREAD_DST_LINK, KNET_THREAD_REGISTERED);
437 savederrno = pthread_create(&knet_h->dst_link_handler_thread, &attr,
438 _handle_dst_link_handler_thread, (void *) knet_h);
439 if (savederrno) {
440 log_err(knet_h, KNET_SUB_HANDLE, "Unable to start dst cache thread: %s",
441 strerror(savederrno));
442 goto exit_fail;
443 }
444
445 set_thread_status(knet_h, KNET_THREAD_TX, KNET_THREAD_REGISTERED);
446 savederrno = pthread_create(&knet_h->send_to_links_thread, &attr,
447 _handle_send_to_links_thread, (void *) knet_h);
448 if (savederrno) {
449 log_err(knet_h, KNET_SUB_HANDLE, "Unable to start datafd to link thread: %s",
450 strerror(savederrno));
451 goto exit_fail;
452 }
453
454 set_thread_status(knet_h, KNET_THREAD_RX, KNET_THREAD_REGISTERED);
455 savederrno = pthread_create(&knet_h->recv_from_links_thread, &attr,
456 _handle_recv_from_links_thread, (void *) knet_h);
457 if (savederrno) {
458 log_err(knet_h, KNET_SUB_HANDLE, "Unable to start link to datafd thread: %s",
459 strerror(savederrno));
460 goto exit_fail;
461 }
462
463 set_thread_status(knet_h, KNET_THREAD_HB, KNET_THREAD_REGISTERED);
464 savederrno = pthread_create(&knet_h->heartbt_thread, &attr,
465 _handle_heartbt_thread, (void *) knet_h);
466 if (savederrno) {
467 log_err(knet_h, KNET_SUB_HANDLE, "Unable to start heartbeat thread: %s",
468 strerror(savederrno));
469 goto exit_fail;
470 }
471
472 savederrno = pthread_attr_destroy(&attr);
473 if (savederrno) {
474 log_err(knet_h, KNET_SUB_HANDLE, "Unable to destroy pthread attributes: %s",
475 strerror(savederrno));
476 /*
477 * Do not return error code. Error is not critical.
478 */
479 }
480
481 return 0;
482
483 exit_fail:
484 errno = savederrno;
485 return -1;
486 }
487
488 static void _stop_threads(knet_handle_t knet_h)
489 {
490 void *retval;
491
492 wait_all_threads_status(knet_h, KNET_THREAD_STOPPED);
493
494 if (knet_h->heartbt_thread) {
495 pthread_cancel(knet_h->heartbt_thread);
496 pthread_join(knet_h->heartbt_thread, &retval);
497 }
498
499 if (knet_h->send_to_links_thread) {
500 pthread_cancel(knet_h->send_to_links_thread);
501 pthread_join(knet_h->send_to_links_thread, &retval);
502 }
503
504 if (knet_h->recv_from_links_thread) {
505 pthread_cancel(knet_h->recv_from_links_thread);
506 pthread_join(knet_h->recv_from_links_thread, &retval);
507 }
508
509 if (knet_h->dst_link_handler_thread) {
510 pthread_cancel(knet_h->dst_link_handler_thread);
511 pthread_join(knet_h->dst_link_handler_thread, &retval);
512 }
513
514 if (knet_h->pmtud_link_handler_thread) {
515 pthread_cancel(knet_h->pmtud_link_handler_thread);
516 pthread_join(knet_h->pmtud_link_handler_thread, &retval);
517 }
518 }
519
520 knet_handle_t knet_handle_new_ex(knet_node_id_t host_id,
521 int log_fd,
522 uint8_t default_log_level,
523 uint64_t flags)
524 {
525 knet_handle_t knet_h;
526 int savederrno = 0;
527 struct rlimit cur;
528
529 if (getrlimit(RLIMIT_NOFILE, &cur) < 0) {
530 return NULL;
531 }
532
533 if ((log_fd < 0) || ((unsigned int)log_fd >= cur.rlim_max)) {
534 errno = EINVAL;
535 return NULL;
536 }
537
538 /*
539 * validate incoming request
540 */
541
542 if ((log_fd) && (default_log_level > KNET_LOG_DEBUG)) {
543 errno = EINVAL;
544 return NULL;
545 }
546
547 if (flags > KNET_HANDLE_FLAG_PRIVILEGED * 2 - 1) {
548 errno = EINVAL;
549 return NULL;
550 }
551
552 /*
553 * allocate handle
554 */
555
556 knet_h = malloc(sizeof(struct knet_handle));
557 if (!knet_h) {
558 errno = ENOMEM;
559 return NULL;
560 }
561 memset(knet_h, 0, sizeof(struct knet_handle));
562
563 /*
564 * setting up some handle data so that we can use logging
565 * also when initializing the library global locks
566 * and trackers
567 */
568
569 knet_h->flags = flags;
570
571 /*
572 * copy config in place
573 */
574
575 knet_h->host_id = host_id;
576 knet_h->logfd = log_fd;
577 if (knet_h->logfd > 0) {
578 memset(&knet_h->log_levels, default_log_level, KNET_MAX_SUBSYSTEMS);
579 }
580
581 /*
582 * set pmtud default timers
583 */
584 knet_h->pmtud_interval = KNET_PMTUD_DEFAULT_INTERVAL;
585
586 /*
587 * set transports reconnect default timers
588 */
589 knet_h->reconnect_int = KNET_TRANSPORT_DEFAULT_RECONNECT_INTERVAL;
590
591 /*
592 * Set the default path for plugins
593 */
594 knet_h->plugin_path = PLUGINPATH;
595
596 /*
597 * Set 'min' stats to the maximum value so the
598 * first value we get is always less
599 */
600 knet_h->stats.tx_compress_time_min = UINT64_MAX;
601 knet_h->stats.rx_compress_time_min = UINT64_MAX;
602 knet_h->stats.tx_crypt_time_min = UINT64_MAX;
603 knet_h->stats.rx_crypt_time_min = UINT64_MAX;
604
605 /*
606 * init global shared bits
607 */
608 savederrno = pthread_mutex_lock(&handle_config_mutex);
609 if (savederrno) {
610 log_err(knet_h, KNET_SUB_HANDLE, "Unable to get handle mutex lock: %s",
611 strerror(savederrno));
612 free(knet_h);
613 knet_h = NULL;
614 errno = savederrno;
615 return NULL;
616 }
617
618 if (!handle_list_init) {
619 qb_list_init(&handle_list.head);
620 handle_list_init = 1;
621 }
622
623 qb_list_add(&knet_h->list, &handle_list.head);
624
625 /*
626 * init global shlib tracker
627 */
628 if (_init_shlib_tracker(knet_h) < 0) {
629 savederrno = errno;
630 log_err(knet_h, KNET_SUB_HANDLE, "Unable to init handle tracker: %s",
631 strerror(savederrno));
632 errno = savederrno;
633 pthread_mutex_unlock(&handle_config_mutex);
634 goto exit_fail;
635 }
636
637 pthread_mutex_unlock(&handle_config_mutex);
638
639 /*
640 * init main locking structures
641 */
642
643 if (_init_locks(knet_h)) {
644 savederrno = errno;
645 goto exit_fail;
646 }
647
648 /*
649 * init sockets
650 */
651
652 if (_init_socks(knet_h)) {
653 savederrno = errno;
654 goto exit_fail;
655 }
656
657 /*
658 * allocate packet buffers
659 */
660
661 if (_init_buffers(knet_h)) {
662 savederrno = errno;
663 goto exit_fail;
664 }
665
666 if (compress_init(knet_h)) {
667 savederrno = errno;
668 goto exit_fail;
669 }
670
671 /*
672 * create epoll fds
673 */
674
675 if (_init_epolls(knet_h)) {
676 savederrno = errno;
677 goto exit_fail;
678 }
679
680 /*
681 * start transports
682 */
683
684 if (start_all_transports(knet_h)) {
685 savederrno = errno;
686 goto exit_fail;
687 }
688
689 /*
690 * start internal threads
691 */
692
693 if (_start_threads(knet_h)) {
694 savederrno = errno;
695 goto exit_fail;
696 }
697
698 wait_all_threads_status(knet_h, KNET_THREAD_STARTED);
699
700 errno = 0;
701 return knet_h;
702
703 exit_fail:
704 knet_handle_free(knet_h);
705 errno = savederrno;
706 return NULL;
707 }
708
709 knet_handle_t knet_handle_new(knet_node_id_t host_id,
710 int log_fd,
711 uint8_t default_log_level)
712 {
713 return knet_handle_new_ex(host_id, log_fd, default_log_level, KNET_HANDLE_FLAG_PRIVILEGED);
714 }
715
716 int knet_handle_free(knet_handle_t knet_h)
717 {
718 int savederrno = 0;
719
720 if (!_is_valid_handle(knet_h)) {
721 return -1;
722 }
723
724 savederrno = get_global_wrlock(knet_h);
725 if (savederrno) {
726 log_err(knet_h, KNET_SUB_HANDLE, "Unable to get write lock: %s",
727 strerror(savederrno));
728 errno = savederrno;
729 return -1;
730 }
731
732 if (knet_h->host_head != NULL) {
733 savederrno = EBUSY;
734 log_err(knet_h, KNET_SUB_HANDLE,
735 "Unable to free handle: host(s) or listener(s) are still active: %s",
736 strerror(savederrno));
737 pthread_rwlock_unlock(&knet_h->global_rwlock);
738 errno = savederrno;
739 return -1;
740 }
741
742 knet_h->fini_in_progress = 1;
743
744 pthread_rwlock_unlock(&knet_h->global_rwlock);
745
746 _stop_threads(knet_h);
747 stop_all_transports(knet_h);
748 _close_epolls(knet_h);
749 _destroy_buffers(knet_h);
750 _close_socks(knet_h);
751 crypto_fini(knet_h, KNET_MAX_CRYPTO_INSTANCES + 1); /* values above MAX_CRYPTO will release all crypto resources */
752 compress_fini(knet_h, 1);
753 _destroy_locks(knet_h);
754
755 (void)pthread_mutex_lock(&handle_config_mutex);
756 qb_list_del(&knet_h->list);
757 _fini_shlib_tracker();
758 pthread_mutex_unlock(&handle_config_mutex);
759
760 free(knet_h);
761 knet_h = NULL;
762
763 errno = 0;
764 return 0;
765 }
766