GCC Code Coverage Report


Directory: ./
File: pdserv/src/TlsSessionImpl.h
Date: 2023-11-12 04:06:57
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 261 ssize_t PdServ::TlsSession<Parent>::write(const void *buf, size_t len)
40 {
41
2/4
✓ Branch 0 taken 261 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 261 times.
261 if (!buf or !len)
42 return 0;
43 261 ssize_t result = gnutls_record_send(session_.get(), buf, len);
44
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 261 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
261 if (result < 0 and gnutls_error_is_fatal(static_cast<int>(result)))
45 return 0;
46 261 return result;
47 }
48
49 template <typename Parent>
50 4720 ssize_t PdServ::TlsSession<Parent>::read(void *buf, size_t len)
51 {
52 4720 ssize_t result = gnutls_record_recv(session_.get(), buf, len);
53
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 4694 times.
4720 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 4694 times.
✓ Branch 1 taken 26 times.
4720 if (result == GNUTLS_E_PREMATURE_TERMINATION
58
1/2
✓ Branch 0 taken 4694 times.
✗ Branch 1 not taken.
4694 or result == GNUTLS_E_UNEXPECTED_PACKET_LENGTH
59
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4694 times.
4694 or result == GNUTLS_E_SESSION_EOF)
60 26 return 0;
61 4694 return result;
62 }
63
64 template <typename Parent>
65 54 void PdServ::TlsSession<Parent>::initial()
66 {
67 54 gnutls_session_t tls_session = nullptr;
68
69
1/2
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
54 int result = gnutls_init(&tls_session, GNUTLS_SERVER | GNUTLS_NONBLOCK);
70
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 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 54 session_.reset(tls_session);
82
1/2
✓ Branch 16 taken 54 times.
✗ Branch 17 not taken.
54 PdServ::Session::main->initTlsSessionData(tls_session);
83 // session_ptr is more generic for verify callbacks
84
1/2
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
54 gnutls_session_set_ptr(tls_session, static_cast<PdServ::Session *>(this));
85
1/2
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
54 gnutls_transport_set_ptr(tls_session, this);
86
1/2
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
54 gnutls_transport_set_push_function(
87 tls_session,
88 1376 [](void *uptr, const void *buf, size_t count) -> ssize_t {
89 661 auto &This = *reinterpret_cast<TlsSession *>(uptr);
90 661 ssize_t ans = This.Parent::write(buf, count);
91
1/2
✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
661 if (ans >= 0)
92 661 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 54 times.
✗ Branch 4 not taken.
54 gnutls_transport_set_pull_function(
98 19798 tls_session, [](void *uptr, void *buf, size_t count) -> ssize_t {
99 9872 auto &This = *reinterpret_cast<TlsSession *>(uptr);
100 // data available?
101
2/2
✓ Branch 4 taken 56 times.
✓ Branch 5 taken 9816 times.
9872 if (!This.isPendingRead(0)) {
102 56 gnutls_transport_set_errno(This.session_.get(), EAGAIN);
103 56 return -1;
104 }
105 9816 const ssize_t ans = This.Parent::read(buf, count);
106
107
1/2
✓ Branch 0 taken 9816 times.
✗ Branch 1 not taken.
9816 if (ans >= 0)
108 9816 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 54 times.
✗ Branch 5 not taken.
54 Parent::initial();
115
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 for (int i = 0; i < 100; ++i) {
116
1/2
✓ Branch 3 taken 108 times.
✗ Branch 4 not taken.
108 const int result = gnutls_handshake(session_.get());
117
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 58 times.
108 if (result == GNUTLS_E_SUCCESS)
118 100 return;
119
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 4 times.
58 if (result == GNUTLS_E_AGAIN)
120 {
121
1/2
✓ Branch 4 taken 54 times.
✗ Branch 5 not taken.
54 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 54 void PdServ::TlsSession<Parent>::final()
143 {
144
1/2
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
54 if (session_)
145 54 gnutls_bye(session_.get(), GNUTLS_SHUT_RDWR);
146 54 Parent::final();
147 54 }
148
149 #endif // PDSERV_TLSSESSION_IMPL_H
150