OpenVPN 3 Core Library
Loading...
Searching...
No Matches
timestr.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// Function to return the current date/time as a string.
13
14#ifndef OPENVPN_TIME_TIMESTR_H
15#define OPENVPN_TIME_TIMESTR_H
16
17#include <string>
18#include <cstring> // for std::strlen and std::memset
19#include <time.h>
20#include <stdio.h>
21#include <ctype.h>
22#include <cstdint> // for std::uint64_t
23
27
28#if defined(OPENVPN_PLATFORM_WIN)
29#include <windows.h>
30#else
31#include <sys/time.h>
32#endif
33
34namespace openvpn {
35
36#if defined(OPENVPN_PLATFORM_WIN)
37
38inline std::string date_time(const time_t now)
39{
40 struct tm *lt = localtime(&now);
41 char *ret = asctime(lt);
42 const size_t len = std::strlen(ret);
43 if (len > 0 && ret[len - 1] == '\n')
44 ret[len - 1] = '\0';
45 return ret;
46}
47
48inline std::string date_time()
49{
50 const time_t now = time(NULL);
51 return date_time(now);
52}
53
54inline std::string date_time_store_time_t(time_t &save)
55{
56 save = time(NULL);
57 return date_time(save);
58}
59
60#else
61
62inline std::string date_time(const time_t t)
63{
64 struct tm lt;
65 char buf[64];
66
67 std::memset(&lt, 0, sizeof(lt));
68 if (!localtime_r(&t, &lt))
69 return "LOCALTIME_ERROR";
70 if (!asctime_r(&lt, buf))
71 return "ASCTIME_ERROR";
72 const size_t len = std::strlen(buf);
73 if (len > 0 && buf[len - 1] == '\n')
74 buf[len - 1] = '\0';
75 return std::string(buf);
76}
77
78inline std::string date_time_utc(const time_t t)
79{
80 struct tm lt;
81 char buf[64];
82
83 std::memset(&lt, 0, sizeof(lt));
84 if (!gmtime_r(&t, &lt))
85 return "GMTIME_ERROR";
86 if (!asctime_r(&lt, buf))
87 return "ASCTIME_ERROR";
88 const size_t len = std::strlen(buf);
89 if (len > 0 && buf[len - 1] == '\n')
90 buf[len - 1] = '\0';
91 return std::string(buf);
92}
93
94// msecs == false : Tue Feb 17 01:24:30 2015
95// msecs == true : Tue Feb 17 01:24:30.123 2015
96inline std::string date_time(const struct timeval *tv, const bool msecs)
97{
98 const std::string dt = date_time(tv->tv_sec);
99 if (msecs)
100 {
101 // find correct position in string to insert milliseconds
102 const size_t pos = dt.find_last_of(':');
103 if (pos != std::string::npos
104 && pos + 3 < dt.length()
105 && string::is_digit(dt[pos + 1])
106 && string::is_digit(dt[pos + 2])
107 && string::is_space(dt[pos + 3]))
108 {
109 char ms[5];
110 ::snprintf(ms, sizeof(ms), ".%03u", static_cast<unsigned int>(tv->tv_usec / 1000));
111 return dt.substr(0, pos + 3) + ms + dt.substr(pos + 3);
112 }
113 }
114 return dt;
115}
116
117inline std::string nanosec_time_to_string(const std::uint64_t ns_time)
118{
119 const std::uint64_t sec = ns_time / std::uint64_t(1000000000);
120 const std::uint64_t ns = ns_time % std::uint64_t(1000000000);
121
122 const std::string dt = date_time_utc(sec);
123
124 // find correct position in string to insert nanoseconds
125 const size_t pos = dt.find_last_of(':');
126 if (pos != std::string::npos
127 && pos + 3 < dt.length()
128 && string::is_digit(dt[pos + 1])
129 && string::is_digit(dt[pos + 2])
130 && string::is_space(dt[pos + 3]))
131 {
132 char ms[11];
133 ::snprintf(ms, sizeof(ms), ".%09u", (unsigned int)ns);
134 return dt.substr(0, pos + 3) + ms + dt.substr(pos + 3);
135 }
136 return dt;
137}
138
139inline std::string date_time()
140{
141 struct timeval tv;
142 if (::gettimeofday(&tv, nullptr) < 0)
143 {
144 tv.tv_sec = 0;
145 tv.tv_usec = 0;
146 }
147 return date_time(&tv, true);
148}
149
150inline std::string date_time_store_time_t(time_t &save)
151{
152 struct timeval tv;
153 if (::gettimeofday(&tv, nullptr) < 0)
154 {
155 tv.tv_sec = 0;
156 tv.tv_usec = 0;
157 }
158 save = tv.tv_sec;
159 return date_time(&tv, true);
160}
161
162#endif
163
164inline std::string date_time_rfc822(const time_t t)
165{
166 struct tm lt;
167 char buf[64];
168
169#if defined(OPENVPN_PLATFORM_WIN)
170 if (gmtime_s(&lt, &t))
171 return "";
172 // MinGW doesn't yet support %T, so use %H:%M:%S
173 // https://sourceforge.net/p/mingw-w64/bugs/793/
174 if (!strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", &lt))
175 return "";
176#else
177 if (!gmtime_r(&t, &lt))
178 return "";
179 if (!strftime(buf, sizeof(buf), "%a, %d %b %Y %T %Z", &lt))
180 return "";
181#endif
182 return std::string(buf);
183}
184
185inline std::string date_time_rfc822()
186{
187 return date_time_rfc822(::time(nullptr));
188}
189
190} // namespace openvpn
191
192#endif
bool is_digit(const char c)
Definition string.hpp:284
bool is_space(const char c)
Definition string.hpp:279
Support deferred server-side state creation when client connects.
Definition ovpncli.cpp:95
std::string nanosec_time_to_string(const std::uint64_t ns_time)
Definition timestr.hpp:117
std::string date_time_store_time_t(time_t &save)
Definition timestr.hpp:150
std::string date_time_rfc822()
Definition timestr.hpp:185
std::string date_time_utc(const time_t t)
Definition timestr.hpp:78
std::string date_time()
Definition timestr.hpp:139
std::string ret