7 enum class IOState { Done, NeedRead, NeedWrite };
12 virtual ~TLSConnection() { }
13 virtual void doHandshake() = 0;
14 virtual IOState tryHandshake() = 0;
15 virtual size_t read(void* buffer, size_t bufferSize, unsigned int readTimeout, unsigned int totalTimeout=0) = 0;
16 virtual size_t write(const void* buffer, size_t bufferSize, unsigned int writeTimeout) = 0;
17 virtual IOState tryWrite(std::vector<uint8_t>& buffer, size_t& pos, size_t toWrite) = 0;
18 virtual IOState tryRead(std::vector<uint8_t>& buffer, size_t& pos, size_t toRead) = 0;
19 virtual std::string getServerNameIndication() = 0;
20 virtual void close() = 0;
31 d_rotatingTicketsKey.clear();
34 virtual std::unique_ptr<TLSConnection> getConnection(int socket, unsigned int timeout, time_t now) = 0;
35 virtual void rotateTicketsKey(time_t now) = 0;
36 virtual void loadTicketsKeys(const std::string& file)
38 throw std::runtime_error("This TLS backend does not have the capability to load a tickets key from a file");
41 void handleTicketsKeyRotation(time_t now)
43 if (d_ticketsKeyRotationDelay != 0 && now > d_ticketsKeyNextRotation) {
44 if (d_rotatingTicketsKey.test_and_set()) {
45 /* someone is already rotating */
49 rotateTicketsKey(now);
50 d_rotatingTicketsKey.clear();
52 catch(const std::runtime_error& e) {
53 d_rotatingTicketsKey.clear();
54 throw std::runtime_error(std::string("Error generating a new tickets key for TLS context:") + e.what());
57 d_rotatingTicketsKey.clear();
63 time_t getNextTicketsKeyRotation() const
65 return d_ticketsKeyNextRotation;
68 virtual size_t getTicketsKeysCount() = 0;
71 std::atomic_flag d_rotatingTicketsKey;
72 time_t d_ticketsKeyRotationDelay{0};
73 time_t d_ticketsKeyNextRotation{0};
81 void rotateTicketsKey(time_t now)
83 if (d_ctx != nullptr) {
84 d_ctx->rotateTicketsKey(now);
88 void loadTicketsKeys(const std::string& file)
90 if (d_ctx != nullptr) {
91 d_ctx->loadTicketsKeys(file);
95 std::shared_ptr<TLSCtx> getContext()
105 size_t getTicketsKeysCount()
107 if (d_ctx != nullptr) {
108 return d_ctx->getTicketsKeysCount();
114 static std::string timeToString(time_t rotationTime)
119 localtime_r(&rotationTime, &date_tm);
120 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &date_tm);
122 return std::string(buf);
125 time_t getTicketsKeyRotationDelay() const
127 return d_ticketsKeyRotationDelay;
130 std::string getNextTicketsKeyRotation() const
134 if (d_ctx != nullptr) {
135 res = timeToString(d_ctx->getNextTicketsKeyRotation());
141 std::vector<std::pair<std::string, std::string>> d_certKeyPairs;
143 std::string d_ciphers;
144 std::string d_ciphers13;
145 std::string d_provider;
146 std::string d_ticketKeyFile;
148 size_t d_maxStoredSessions{20480};
149 time_t d_ticketsKeyRotationDelay{43200};
150 uint8_t d_numberOfTicketsKeys{5};
151 bool d_enableTickets{true};
154 std::shared_ptr<TLSCtx> d_ctx{nullptr};
161 TCPIOHandler(int socket, unsigned int timeout, std::shared_ptr<TLSCtx> ctx, time_t now): d_socket(socket)
164 d_conn = ctx->getConnection(d_socket, timeout, now);
173 else if (d_socket != -1) {
174 shutdown(d_socket, SHUT_RDWR);
178 IOState tryHandshake()
181 return d_conn->tryHandshake();
183 return IOState::Done;
186 size_t read(void* buffer, size_t bufferSize, unsigned int readTimeout, unsigned int totalTimeout=0)
189 return d_conn->read(buffer, bufferSize, readTimeout, totalTimeout);
191 return readn2WithTimeout(d_socket, buffer, bufferSize, readTimeout, totalTimeout);
195 /* Tries to read exactly toRead bytes into the buffer, starting at position pos.
196 Updates pos everytime a successful read occurs,
197 throws an std::runtime_error in case of IO error,
198 return Done when toRead bytes have been read, needRead or needWrite if the IO operation
201 IOState tryRead(std::vector<uint8_t>& buffer, size_t& pos, size_t toRead)
203 if (buffer.size() < (pos + toRead)) {
204 throw std::out_of_range("Calling tryRead() with a too small buffer (" + std::to_string(buffer.size()) + ") for a read of " + std::to_string(toRead) + " bytes starting at " + std::to_string(pos));
208 return d_conn->tryRead(buffer, pos, toRead);
213 ssize_t res = ::read(d_socket, reinterpret_cast<char*>(&buffer.at(pos)), toRead - got);
215 throw runtime_error("EOF while reading message");
218 if (errno == EAGAIN || errno == EWOULDBLOCK) {
219 return IOState::NeedRead;
222 throw std::runtime_error(std::string("Error while reading message: ") + strerror(errno));
226 pos += static_cast<size_t>(res);
227 got += static_cast<size_t>(res);
229 while (got < toRead);
231 return IOState::Done;
234 /* Tries to write exactly toWrite bytes from the buffer, starting at position pos.
235 Updates pos everytime a successful write occurs,
236 throws an std::runtime_error in case of IO error,
237 return Done when toWrite bytes have been written, needRead or needWrite if the IO operation
240 IOState tryWrite(std::vector<uint8_t>& buffer, size_t& pos, size_t toWrite)
243 return d_conn->tryWrite(buffer, pos, toWrite);
248 ssize_t res = ::write(d_socket, reinterpret_cast<char*>(&buffer.at(pos)), toWrite - sent);
250 throw runtime_error("EOF while sending message");
253 if (errno == EAGAIN || errno == EWOULDBLOCK) {
254 return IOState::NeedWrite;
257 throw std::runtime_error(std::string("Error while writing message: ") + strerror(errno));
261 pos += static_cast<size_t>(res);
262 sent += static_cast<size_t>(res);
264 while (sent < toWrite);
266 return IOState::Done;
269 size_t write(const void* buffer, size_t bufferSize, unsigned int writeTimeout)
272 return d_conn->write(buffer, bufferSize, writeTimeout);
275 return writen2WithTimeout(d_socket, buffer, bufferSize, writeTimeout);
279 std::string getServerNameIndication()
282 return d_conn->getServerNameIndication();
284 return std::string();
288 std::unique_ptr<TLSConnection> d_conn{nullptr};