GCC Code Coverage Report


Directory: ./
File: pdserv/src/TlsSessionImpl.h
Date: 2024-11-17 04:08:36
Exec Total Coverage
Lines: 53 64 82.8%
Branches: 47 126 37.3%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright 2021 Bjarne von Horn (vh at igh dot de)
4 *
5 * This file is part of the pdserv library.
6 *
7 * The pdserv library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation, either version 3 of the License, or (at
10 * your option) any later version.
11 *
12 * The pdserv library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with the pdserv library. If not, see <http://www.gnu.org/licenses/>.
19 *
20 *****************************************************************************/
21
22 #ifndef PDSERV_TLSSESSION_IMPL_H
23 #define PDSERV_TLSSESSION_IMPL_H
24
25 #include "PThread.h"
26 #include "Session.h"
27 #include "TlsSession.h"
28
29 #include <cerrno>
30 #include <cstddef>
31 #include <cstring>
32 #include <gnutls/gnutls.h>
33 #include <log4cplus/logger.h>
34 #include <log4cplus/loggingmacros.h>
35 #include <memory>
36 #include <stdexcept>
37
38 template <typename Parent>
39 471 ssize_t PdServ::TlsSession<Parent>::write(const void *buf, size_t len)
40 {
41
2/4
✓ Branch 0 taken 471 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 471 times.
471 if (!buf or !len)
42 return 0;
43 471 ssize_t result = gnutls_record_send(session_.get(), buf, len);
44
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 471 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
471 if (result < 0 and gnutls_error_is_fatal(static_cast<int>(result)))
45 return 0;
46 471 return result;
47 }
48
49 template <typename Parent>
50 6264 ssize_t PdServ::TlsSession<Parent>::read(void *buf, size_t len)
51 {
52 6264 ssize_t result = gnutls_record_recv(session_.get(), buf, len);
53
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 6238 times.
6264 if (result < 0
54
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 and (result == GNUTLS_E_AGAIN
55
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
26 or !gnutls_error_is_fatal(static_cast<int>(result))))
56 return -EAGAIN;
57
2/2
✓ Branch 0 taken 6238 times.
✓ Branch 1 taken 26 times.
6264 if (result == GNUTLS_E_PREMATURE_TERMINATION
58
1/2
✓ Branch 0 taken 6238 times.
✗ Branch 1 not taken.
6238 or result == GNUTLS_E_UNEXPECTED_PACKET_LENGTH
59
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6238 times.
6238 or result == GNUTLS_E_SESSION_EOF)
60 26 return 0;
61 6238 return result;
62 }
63
64 template <typename Parent>
65 66 void PdServ::TlsSession<Parent>::initial()
66 {
67 66 gnutls_session_t tls_session = nullptr;
68
69
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 int result = gnutls_init(&tls_session, GNUTLS_SERVER | GNUTLS_NONBLOCK);
70
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (result) {
71 LOG4CPLUS_FATAL(
72 PdServ::Session::log,
73 LOG4CPLUS_TEXT("gnutls_init() failed: ")
74 << LOG4CPLUS_C_STR_TO_TSTRING(gnutls_strerror(result))
75 << LOG4CPLUS_TEXT(" (")
76 << LOG4CPLUS_C_STR_TO_TSTRING(
77 gnutls_strerror_name(result))
78 << LOG4CPLUS_TEXT(")"));
79 throw pthread::Thread::CancelThread();
80 }
81 66 session_.reset(tls_session);
82
1/2
✓ Branch 16 taken 66 times.
✗ Branch 17 not taken.
66 PdServ::Session::main->initTlsSessionData(tls_session);
83 // session_ptr is more generic for verify callbacks
84
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 gnutls_session_set_ptr(tls_session, static_cast<PdServ::Session *>(this));
85
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 gnutls_transport_set_ptr(tls_session, this);
86
1/2
✓ Branch 3 taken 66 times.
✗ Branch 4 not taken.
66 gnutls_transport_set_push_function(
87 tls_session,
88 1988 [](void *uptr, const void *buf, size_t count) -> ssize_t {
89 961 auto &This = *reinterpret_cast<TlsSession *>(uptr);
90 961 ssize_t ans = This.Parent::write(buf, count);
91
1/2
✓ Branch 0 taken 961 times.
✗ Branch 1 not taken.
961 if (ans >= 0)
92 961 return ans;
93 gnutls_transport_set_errno(
94 This.session_.get(), static_cast<int>(ans));
95 return -1;
96 });
97
1/2
✓ Branch 3 taken 66 times.
✗ Branch 4 not taken.
66 gnutls_transport_set_pull_function(
98 26232 tls_session, [](void *uptr, void *buf, size_t count) -> ssize_t {
99 13083 auto &This = *reinterpret_cast<TlsSession *>(uptr);
100 // data available?
101
2/2
✓ Branch 4 taken 83 times.
✓ Branch 5 taken 13000 times.
13083 if (!This.isPendingRead(0)) {
102 83 gnutls_transport_set_errno(This.session_.get(), EAGAIN);
103 83 return -1;
104 }
105 13000 const ssize_t ans = This.Parent::read(buf, count);
106
107
1/2
✓ Branch 0 taken 13000 times.
✗ Branch 1 not taken.
13000 if (ans >= 0)
108 13000 return ans;
109 gnutls_transport_set_errno(
110 This.session_.get(), -static_cast<int>(ans));
111 return -1;
112 });
113
114
1/2
✓ Branch 4 taken 66 times.
✗ Branch 5 not taken.
66 Parent::initial();
115
1/2
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
147 for (int i = 0; i < 100; ++i) {
116
1/2
✓ Branch 3 taken 147 times.
✗ Branch 4 not taken.
147 const int result = gnutls_handshake(session_.get());
117
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 85 times.
147 if (result == GNUTLS_E_SUCCESS)
118 124 return;
119
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 4 times.
85 if (result == GNUTLS_E_AGAIN)
120 {
121
1/2
✓ Branch 4 taken 81 times.
✗ Branch 5 not taken.
81 Parent::isPendingRead(40);
122 }
123
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 else if (gnutls_error_is_fatal(result)) {
124
14/28
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 4 times.
✗ Branch 18 not taken.
✓ Branch 22 taken 4 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 4 times.
✗ Branch 26 not taken.
✓ Branch 29 taken 4 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 4 times.
✗ Branch 33 not taken.
✓ Branch 37 taken 4 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 4 times.
✗ Branch 41 not taken.
✓ Branch 44 taken 4 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 4 times.
✗ Branch 48 not taken.
✓ Branch 59 taken 4 times.
✗ Branch 60 not taken.
✓ Branch 63 taken 4 times.
✗ Branch 64 not taken.
4 LOG4CPLUS_FATAL(
125 PdServ::Session::log,
126 LOG4CPLUS_TEXT("gnutls_handshake() failed: ")
127 << LOG4CPLUS_C_STR_TO_TSTRING(
128 gnutls_strerror(result))
129 << LOG4CPLUS_TEXT(" (")
130 << LOG4CPLUS_C_STR_TO_TSTRING(
131 gnutls_strerror_name(result))
132 << LOG4CPLUS_TEXT(")"));
133 4 throw pthread::Thread::CancelThread();
134 }
135 }
136 LOG4CPLUS_FATAL(
137 PdServ::Session::log, LOG4CPLUS_TEXT("gnutls_handshake() failed"));
138 throw pthread::Thread::CancelThread();
139 }
140
141 template <typename Parent>
142 66 void PdServ::TlsSession<Parent>::final()
143 {
144
1/2
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
66 if (session_)
145 66 gnutls_bye(session_.get(), GNUTLS_SHUT_RDWR);
146 66 Parent::final();
147 66 }
148
149 #endif // PDSERV_TLSSESSION_IMPL_H
150