1 /*
2  * Copyright (c) 2023 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 "stream_server.h"
17 
18 #include <cinttypes>
19 
20 #include <sys/socket.h>
21 
22 #include "sensor_errors.h"
23 
24 #undef LOG_TAG
25 #define LOG_TAG "StreamServer"
26 
27 namespace OHOS {
28 namespace Sensors {
29 namespace {
30 constexpr int32_t INVALID_PID = -1;
31 constexpr int32_t INVALID_FD = -1;
32 } // namespace
33 
~StreamServer()34 StreamServer::~StreamServer()
35 {
36     CALL_LOG_ENTER;
37     std::lock_guard<std::mutex> sessionLock(sessionMutex_);
38     idxPidMap_.clear();
39     for (const auto &item : sessionsMap_) {
40         item.second->Close();
41     }
42     sessionsMap_.clear();
43 }
44 
GetClientFd(int32_t pid)45 int32_t StreamServer::GetClientFd(int32_t pid)
46 {
47     std::lock_guard<std::mutex> sessionLock(sessionMutex_);
48     auto it = idxPidMap_.find(pid);
49     return it == idxPidMap_.end() ? INVALID_FD : it->second;
50 }
51 
GetClientPid(int32_t fd)52 int32_t StreamServer::GetClientPid(int32_t fd)
53 {
54     std::lock_guard<std::mutex> sessionLock(sessionMutex_);
55     auto it = sessionsMap_.find(fd);
56     return it == sessionsMap_.end() ? INVALID_PID : it->second->GetPid();
57 }
58 
GetSession(int32_t fd)59 SessionPtr StreamServer::GetSession(int32_t fd)
60 {
61     std::lock_guard<std::mutex> sessionLock(sessionMutex_);
62     auto it = sessionsMap_.find(fd);
63     if (it == sessionsMap_.end()) {
64         SEN_HILOGE("Session not found");
65         return nullptr;
66     }
67     CHKPP(it->second);
68     return it->second->GetSharedPtr();
69 }
70 
GetSessionByPid(int32_t pid)71 SessionPtr StreamServer::GetSessionByPid(int32_t pid)
72 {
73     int32_t fd = GetClientFd(pid);
74     if (fd <= 0) {
75         SEN_HILOGE("Session not found");
76         return nullptr;
77     }
78     return GetSession(fd);
79 }
80 
AddSocketPairInfo(int32_t uid,int32_t pid,int32_t tokenType,int32_t & serverFd,int32_t & clientFd)81 int32_t StreamServer::AddSocketPairInfo(int32_t uid, int32_t pid, int32_t tokenType,
82     int32_t &serverFd, int32_t &clientFd)
83 {
84     CALL_LOG_ENTER;
85     int32_t sockFds[2] = { -1 };
86     if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockFds) != 0) {
87         SEN_HILOGE("Socketpair failed, errno:%{public}d", errno);
88         return ERROR;
89     }
90     serverFd = sockFds[0];
91     clientFd = sockFds[1];
92     if (serverFd < 0 || clientFd < 0) {
93         SEN_HILOGE("ServerFd or clientFd is invalid");
94         return ERROR;
95     }
96     static constexpr size_t bufferSize = 32 * 1024;
97     SessionPtr sess = nullptr;
98     if (setsockopt(serverFd, SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)) != 0) {
99         SEN_HILOGE("Setsockopt serverFd send buffer size failed, errno:%{public}d", errno);
100         goto CLOSE_SOCK;
101     }
102     if (setsockopt(serverFd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)) != 0) {
103         SEN_HILOGE("Setsockopt serverFd recv buffer size failed, errno:%{public}d", errno);
104         goto CLOSE_SOCK;
105     }
106     if (setsockopt(clientFd, SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)) != 0) {
107         SEN_HILOGE("Setsockopt clientFd send buffer size failed, errno:%{public}d", errno);
108         goto CLOSE_SOCK;
109     }
110     if (setsockopt(clientFd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)) != 0) {
111         SEN_HILOGE("Setsockopt clientFd recv buffer size failed, errno:%{public}d", errno);
112         goto CLOSE_SOCK;
113     }
114     sess = std::make_shared<StreamSession>("", serverFd, uid, pid);
115     sess->SetTokenType(tokenType);
116     if (!AddSession(sess)) {
117         SEN_HILOGE("AddSession fail");
118         goto CLOSE_SOCK;
119     }
120     return ERR_OK;
121 
122 CLOSE_SOCK:
123     close(serverFd);
124     close(clientFd);
125     return ERROR;
126 }
127 
AddSession(SessionPtr sess)128 bool StreamServer::AddSession(SessionPtr sess)
129 {
130     CALL_LOG_ENTER;
131     CHKPF(sess);
132     auto fd = sess->GetFd();
133     if (fd < 0) {
134         SEN_HILOGE("Fd is Invalid");
135         return false;
136     }
137     auto pid = sess->GetPid();
138     if (pid <= 0) {
139         SEN_HILOGE("Pid is invalid");
140         return false;
141     }
142     std::lock_guard<std::mutex> sessionLock(sessionMutex_);
143     if (sessionsMap_.size() > MAX_SESSON_ALARM) {
144         SEN_HILOGE("Too many clients, size:%{public}zu", sessionsMap_.size());
145         return false;
146     }
147     idxPidMap_[pid] = fd;
148     sessionsMap_[fd] = sess;
149     return true;
150 }
151 
DelSession(int32_t pid)152 void StreamServer::DelSession(int32_t pid)
153 {
154     CALL_LOG_ENTER;
155     std::lock_guard<std::mutex> sessionLock(sessionMutex_);
156     auto pidIt = idxPidMap_.find(pid);
157     if (pidIt == idxPidMap_.end()) {
158         SEN_HILOGW("Pid session not exist");
159         return;
160     }
161     int32_t fd = pidIt->second;
162     idxPidMap_.erase(pidIt);
163     auto fdIt = sessionsMap_.find(fd);
164     if (fdIt != sessionsMap_.end()) {
165         sessionsMap_.erase(fdIt);
166     }
167     if (fd >= 0) {
168         int32_t ret = close(fd);
169         if (ret != 0) {
170             SEN_HILOGE("Socket fd close failed, ret:%{public}d, errno:%{public}d", ret, errno);
171         }
172     }
173 }
174 } // namespace Sensors
175 } // namespace OHOS