1 /*
2 * Copyright (C) 2021-2022 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 #include "socket_listener.h"
17 #include <sys/epoll.h>
18 #include <sys/eventfd.h>
19 #include <unistd.h>
20 #include "log.h"
21
22 namespace OHOS {
23 namespace bluetooth {
GetInstance()24 SocketThread &SocketThread::GetInstance()
25 {
26 static SocketThread instance;
27 return instance;
28 }
29
Initialize()30 bool SocketThread::Initialize()
31 {
32 LOG_INFO("[SocketListener]: %{public}s", __func__);
33 epollFd_ = epoll_create1(EPOLL_CLOEXEC);
34 stopFd_ = eventfd(0, 0);
35 if (epollFd_ == -1 || stopFd_ == -1) {
36 LOG_ERROR("[SocketListener]: Create epoll failed!!");
37 return false;
38 }
39
40 int ret;
41 struct epoll_event event = {};
42 event.data.ptr = nullptr;
43 event.events = EPOLLIN;
44
45 CHECK_EXCEPT_INTR(ret = epoll_ctl(epollFd_, EPOLL_CTL_ADD, stopFd_, &event));
46 if (ret == -1) {
47 LOG_ERROR("[SocketListener]: Epoll add stop-event failed!!");
48 return false;
49 }
50
51 thread_ = std::make_unique<std::thread>(&SocketThread::OnListenEvents, this);
52 count_ = 0;
53
54 return true;
55 }
56
Uninitialize()57 bool SocketThread::Uninitialize()
58 {
59 LOG_INFO("[SocketListener]: %{public}s", __func__);
60 eventfd_write(stopFd_, 1);
61 if (thread_ && thread_->joinable()) {
62 thread_->join();
63 thread_ = nullptr;
64 }
65
66 std::lock_guard<std::mutex> lock(epollFdMutex_);
67 if (epollFd_ != -1) {
68 close(epollFd_);
69 epollFd_ = -1;
70 }
71 if (stopFd_ != -1) {
72 close(stopFd_);
73 stopFd_ = -1;
74 }
75 return true;
76 }
77
AddSocket(int fd,int flag,Socket & sock)78 bool SocketThread::AddSocket(int fd, int flag, Socket &sock)
79 {
80 LOG_INFO("[SocketListener]: %{public}s", __func__);
81
82 if (count_ >= MAX_EPOLL) {
83 LOG_ERROR("[SocketListener]: Too many sockets..");
84 return false;
85 }
86
87 {
88 std::lock_guard<std::mutex> lock(mutex_);
89 fdMap_[&sock] = fd;
90 }
91
92 int ret;
93 struct epoll_event event = {};
94 event.data.ptr = &sock;
95 if (flag == 1) {
96 event.events = EPOLLRDHUP | EPOLLERR | EPOLLIN | EPOLLOUT | EPOLLONESHOT;
97 ret = epoll_ctl(epollFd_, EPOLL_CTL_MOD, fd, &event);
98 } else {
99 count_++;
100 event.events = EPOLLRDHUP | EPOLLERR | EPOLLIN;
101 ret = epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &event);
102 }
103
104 LOG_INFO("[SocketListener]: epollFd: %{public}d, fd:%{public}d, errno:%{public}d", epollFd_, fd, errno);
105 if (ret == -1) {
106 LOG_ERROR("[SocketListener]: add Socket-Event failed");
107 return false;
108 }
109
110 return true;
111 }
112
OnListenEvents(void)113 void SocketThread::OnListenEvents(void)
114 {
115 struct epoll_event events[MAX_EPOLL];
116
117 while (true) {
118 int nfds;
119 CHECK_EXCEPT_INTR(nfds = epoll_wait(epollFd_, events, MAX_EPOLL, -1));
120 if (nfds == -1) {
121 return;
122 }
123
124 for (int i = 0; i < nfds; ++i) {
125 if (events[i].data.ptr == nullptr) {
126 eventfd_t val;
127 eventfd_read(this->stopFd_, &val);
128 return;
129 }
130
131 Socket &sock = *(Socket *)events[i].data.ptr;
132 if (events[i].events & EPOLLIN) {
133 readCallback_(sock);
134 }
135 std::lock_guard<std::mutex> lock(epollFdMutex_);
136 int fd = FindFd(sock);
137 if (events[i].events & EPOLLOUT) {
138 writeCallback_(sock);
139
140 struct epoll_event event = {};
141 event.data.ptr = &sock;
142 event.events = EPOLLRDHUP | EPOLLERR | EPOLLIN;
143 epoll_ctl(epollFd_, EPOLL_CTL_MOD, fd, &event);
144 LOG_DEBUG("[SocketListener]: epollFd: %{public}d, fd:%{public}d, errno:%{public}d",
145 epollFd_, fd, errno);
146 }
147 if (events[i].events & (EPOLLRDHUP | EPOLLERR)) {
148 LOG_INFO("[SocketListener]: remove fd:%{public}d", fd);
149 epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, nullptr);
150 DeleteFd(sock);
151 count_--;
152 LOG_INFO("[SocketListener]: exceptCallback");
153 exceptCallback_(sock);
154 }
155 }
156 }
157 }
158
FindFd(Socket & sock)159 int SocketThread::FindFd(Socket &sock)
160 {
161 std::lock_guard<std::mutex> lock(mutex_);
162 int fd = -1;
163 if (fdMap_.find(&sock) != fdMap_.end()) {
164 fd = fdMap_.at(&sock);
165 } else {
166 LOG_ERROR("[SocketListener]: fd does not exist");
167 }
168 return fd;
169 }
170
DeleteFd(Socket & sock)171 void SocketThread::DeleteFd(Socket &sock)
172 {
173 std::lock_guard<std::mutex> lock(mutex_);
174 fdMap_.erase(&sock);
175 }
176
DeleteSocket(Socket & sock)177 bool SocketThread::DeleteSocket(Socket &sock)
178 {
179 int fd = FindFd(sock);
180 LOG_DEBUG("SocketThread: DeleteSocket fd:%{public}d", fd);
181 std::lock_guard<std::mutex> lock(epollFdMutex_);
182 if ((fd == -1) || (epollFd_ == -1)) {
183 return false;
184 }
185 if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, nullptr) != -1) {
186 DeleteFd(sock);
187 count_--;
188 return true;
189 }
190 LOG_DEBUG("SocketThread: DeleteSocket errno:%{public}d", errno);
191 return false;
192 }
193 } // namespace bluetooth
194 } // namespace OHOS