1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef COMMUNICATIONNETSTACK_TIMEOUT_TIMER_H
17#define COMMUNICATIONNETSTACK_TIMEOUT_TIMER_H
18
19#include <sys/epoll.h>
20#include <sys/timerfd.h>
21
22#include <string.h>
23#include <unistd.h>
24
25#include "epoller.h"
26#include "file_descriptor.h"
27#include "securec.h"
28
29namespace OHOS::NetStack::HttpOverCurl {
30
31static constexpr long MILLISECONDS_IN_SECOND = 1000;
32static constexpr long NANOSECONDS_IN_MILLISECOND = 1000 * 1000;
33
34struct TimeoutTimer {
35    TimeoutTimer()
36    {
37        underlying_ = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
38    }
39
40    ~TimeoutTimer()
41    {
42        close(underlying_);
43    }
44
45    TimeoutTimer(const TimeoutTimer &) = delete;
46    TimeoutTimer(TimeoutTimer &&other) = default;
47
48    void RegisterForPolling(Epoller &poller) const
49    {
50        poller.RegisterMe(underlying_);
51    }
52
53    [[nodiscard]] bool IsItYours(FileDescriptor descriptor) const
54    {
55        return descriptor == underlying_;
56    }
57
58    void Stop()
59    {
60        SetTimeoutMs(0);
61    }
62
63    void SetTimeoutNs(long timeoutNs)
64    {
65        itimerspec its{};
66        memset_s(&its, sizeof(itimerspec), 0, sizeof(itimerspec));
67
68        if (timeoutNs > 0) {
69            its.it_value.tv_nsec = timeoutNs;
70        }
71
72        timerfd_settime(underlying_, 0, &its, nullptr);
73    }
74
75    void SetTimeoutMs(long timeoutMs)
76    {
77        itimerspec its{};
78        memset_s(&its, sizeof(itimerspec), 0, sizeof(itimerspec));
79
80        if (timeoutMs > 0) {
81            its.it_value.tv_sec = timeoutMs / MILLISECONDS_IN_SECOND;
82            its.it_value.tv_nsec = (timeoutMs % MILLISECONDS_IN_SECOND) * NANOSECONDS_IN_MILLISECOND;
83        }
84
85        timerfd_settime(underlying_, 0, &its, nullptr);
86    }
87
88    void ResetEvent()
89    {
90        uint64_t count = 0;
91        read(underlying_, &count, sizeof(uint64_t));
92    }
93
94private:
95    FileDescriptor underlying_;
96};
97
98} // namespace OHOS::NetStack::HttpOverCurl
99
100#endif // COMMUNICATIONNETSTACK_TIMEOUT_TIMER_H
101