Revise API to load cert/key in SSLContext.
[folly.git] / folly / io / async / AsyncTimeout.cpp
1 /*
2  * Copyright 2004-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <folly/io/async/AsyncTimeout.h>
18 #include <folly/io/async/EventBase.h>
19 #include <folly/io/async/EventUtil.h>
20 #include <folly/io/async/Request.h>
21
22 #include <assert.h>
23 #include <glog/logging.h>
24
25 namespace folly {
26
27 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager)
28     : timeoutManager_(timeoutManager) {
29
30   folly_event_set(
31       &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
32   event_.ev_base = nullptr;
33   timeoutManager_->attachTimeoutManager(
34       this,
35       TimeoutManager::InternalEnum::NORMAL);
36 }
37
38 AsyncTimeout::AsyncTimeout(EventBase* eventBase)
39     : timeoutManager_(eventBase) {
40
41   folly_event_set(
42       &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
43   event_.ev_base = nullptr;
44   if (eventBase) {
45     timeoutManager_->attachTimeoutManager(
46       this,
47       TimeoutManager::InternalEnum::NORMAL);
48   }
49 }
50
51 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager,
52                              InternalEnum internal)
53     : timeoutManager_(timeoutManager) {
54
55   folly_event_set(
56       &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
57   event_.ev_base = nullptr;
58   timeoutManager_->attachTimeoutManager(this, internal);
59 }
60
61 AsyncTimeout::AsyncTimeout(EventBase* eventBase, InternalEnum internal)
62     : timeoutManager_(eventBase) {
63
64   folly_event_set(
65       &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
66   event_.ev_base = nullptr;
67   timeoutManager_->attachTimeoutManager(this, internal);
68 }
69
70 AsyncTimeout::AsyncTimeout(): timeoutManager_(nullptr) {
71   folly_event_set(
72       &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
73   event_.ev_base = nullptr;
74 }
75
76 AsyncTimeout::~AsyncTimeout() {
77   cancelTimeout();
78 }
79
80 bool AsyncTimeout::scheduleTimeout(TimeoutManager::timeout_type timeout) {
81   assert(timeoutManager_ != nullptr);
82   context_ = RequestContext::saveContext();
83   return timeoutManager_->scheduleTimeout(this, timeout);
84 }
85
86 bool AsyncTimeout::scheduleTimeout(uint32_t milliseconds) {
87   return scheduleTimeout(TimeoutManager::timeout_type(milliseconds));
88 }
89
90 void AsyncTimeout::cancelTimeout() {
91   if (isScheduled()) {
92     timeoutManager_->cancelTimeout(this);
93   }
94 }
95
96 bool AsyncTimeout::isScheduled() const {
97   return EventUtil::isEventRegistered(&event_);
98 }
99
100 void AsyncTimeout::attachTimeoutManager(
101     TimeoutManager* timeoutManager,
102     InternalEnum internal) {
103   // This also implies no timeout is scheduled.
104   assert(timeoutManager_ == nullptr);
105   assert(timeoutManager->isInTimeoutManagerThread());
106   timeoutManager_ = timeoutManager;
107
108   timeoutManager_->attachTimeoutManager(this, internal);
109 }
110
111 void AsyncTimeout::attachEventBase(
112     EventBase* eventBase,
113     InternalEnum internal) {
114   attachTimeoutManager(eventBase, internal);
115 }
116
117 void AsyncTimeout::detachTimeoutManager() {
118   // Only allow the event base to be changed if the timeout is not
119   // currently installed.
120   if (isScheduled()) {
121     // Programmer bug.  Abort the program.
122     LOG(FATAL) << "detachEventBase() called on scheduled timeout; aborting";
123   }
124
125   if (timeoutManager_) {
126     timeoutManager_->detachTimeoutManager(this);
127     timeoutManager_ = nullptr;
128   }
129 }
130
131 void AsyncTimeout::detachEventBase() {
132   detachTimeoutManager();
133 }
134
135 void AsyncTimeout::libeventCallback(libevent_fd_t fd, short events, void* arg) {
136   AsyncTimeout* timeout = reinterpret_cast<AsyncTimeout*>(arg);
137   assert(libeventFdToFd(fd) == -1);
138   assert(events == EV_TIMEOUT);
139   // prevent unused variable warnings
140   (void)fd;
141   (void)events;
142
143   // double check that ev_flags gets reset when the timeout is not running
144   assert((event_ref_flags(&timeout->event_) & ~EVLIST_INTERNAL) == EVLIST_INIT);
145
146   // this can't possibly fire if timeout->eventBase_ is nullptr
147   timeout->timeoutManager_->bumpHandlingTime();
148
149   RequestContextScopeGuard rctx(timeout->context_);
150
151   timeout->timeoutExpired();
152 }
153
154 } // namespace folly