1c29fa5a6Sopenharmony_ci/*
2c29fa5a6Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License.
5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at
6c29fa5a6Sopenharmony_ci *
7c29fa5a6Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8c29fa5a6Sopenharmony_ci *
9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and
13c29fa5a6Sopenharmony_ci * limitations under the License.
14c29fa5a6Sopenharmony_ci */
15c29fa5a6Sopenharmony_ci
16c29fa5a6Sopenharmony_ci#include "socket_session.h"
17c29fa5a6Sopenharmony_ci
18c29fa5a6Sopenharmony_ci#include <sstream>
19c29fa5a6Sopenharmony_ci
20c29fa5a6Sopenharmony_ci#include <sys/socket.h>
21c29fa5a6Sopenharmony_ci#include <unistd.h>
22c29fa5a6Sopenharmony_ci
23c29fa5a6Sopenharmony_ci#include "proto.h"
24c29fa5a6Sopenharmony_ci
25c29fa5a6Sopenharmony_ci#undef LOG_TAG
26c29fa5a6Sopenharmony_ci#define LOG_TAG "SocketSession"
27c29fa5a6Sopenharmony_ci
28c29fa5a6Sopenharmony_cinamespace OHOS {
29c29fa5a6Sopenharmony_cinamespace Msdp {
30c29fa5a6Sopenharmony_cinamespace DeviceStatus {
31c29fa5a6Sopenharmony_ci
32c29fa5a6Sopenharmony_ciSocketSession::SocketSession(const std::string &programName, int32_t moduleType,
33c29fa5a6Sopenharmony_ci                             int32_t tokenType, int32_t fd, int32_t uid, int32_t pid)
34c29fa5a6Sopenharmony_ci    : fd_(fd), uid_(uid), pid_(pid), tokenType_(tokenType), programName_(programName)
35c29fa5a6Sopenharmony_ci{}
36c29fa5a6Sopenharmony_ci
37c29fa5a6Sopenharmony_ciSocketSession::~SocketSession()
38c29fa5a6Sopenharmony_ci{
39c29fa5a6Sopenharmony_ci    if ((fd_ >= 0) && (::close(fd_) != 0)) {
40c29fa5a6Sopenharmony_ci        FI_HILOGE("close(%{public}d) failed:%{public}s", fd_, ::strerror(errno));
41c29fa5a6Sopenharmony_ci    }
42c29fa5a6Sopenharmony_ci}
43c29fa5a6Sopenharmony_ci
44c29fa5a6Sopenharmony_cibool SocketSession::SendMsg(NetPacket &pkt) const
45c29fa5a6Sopenharmony_ci{
46c29fa5a6Sopenharmony_ci    if (pkt.ChkRWError()) {
47c29fa5a6Sopenharmony_ci        FI_HILOGE("Read and write status is error");
48c29fa5a6Sopenharmony_ci        return false;
49c29fa5a6Sopenharmony_ci    }
50c29fa5a6Sopenharmony_ci    StreamBuffer buf;
51c29fa5a6Sopenharmony_ci    if (!pkt.MakeData(buf)) {
52c29fa5a6Sopenharmony_ci        FI_HILOGE("Failed to buffer packet");
53c29fa5a6Sopenharmony_ci        return false;
54c29fa5a6Sopenharmony_ci    }
55c29fa5a6Sopenharmony_ci    return SendMsg(buf.Data(), buf.Size());
56c29fa5a6Sopenharmony_ci}
57c29fa5a6Sopenharmony_ci
58c29fa5a6Sopenharmony_cibool SocketSession::SendMsg(const char *buf, size_t size) const
59c29fa5a6Sopenharmony_ci{
60c29fa5a6Sopenharmony_ci    CALL_INFO_TRACE;
61c29fa5a6Sopenharmony_ci    CHKPF(buf);
62c29fa5a6Sopenharmony_ci    if ((size == 0) || (size > MAX_PACKET_BUF_SIZE)) {
63c29fa5a6Sopenharmony_ci        FI_HILOGE("buf size:%{public}zu", size);
64c29fa5a6Sopenharmony_ci        return false;
65c29fa5a6Sopenharmony_ci    }
66c29fa5a6Sopenharmony_ci    if (fd_ < 0) {
67c29fa5a6Sopenharmony_ci        FI_HILOGE("The fd_ is less than 0");
68c29fa5a6Sopenharmony_ci        return false;
69c29fa5a6Sopenharmony_ci    }
70c29fa5a6Sopenharmony_ci
71c29fa5a6Sopenharmony_ci    int32_t idx = 0;
72c29fa5a6Sopenharmony_ci    int32_t retryCount = 0;
73c29fa5a6Sopenharmony_ci    const int32_t bufSize = static_cast<int32_t>(size);
74c29fa5a6Sopenharmony_ci    int32_t remSize = bufSize;
75c29fa5a6Sopenharmony_ci    FI_HILOGI("Rem size:%{public}d", remSize);
76c29fa5a6Sopenharmony_ci    while (remSize > 0 && retryCount < SEND_RETRY_LIMIT) {
77c29fa5a6Sopenharmony_ci        retryCount += 1;
78c29fa5a6Sopenharmony_ci        FI_HILOGD("Send message to client (%{public}d, %{public}d)", fd_, pid_);
79c29fa5a6Sopenharmony_ci        ssize_t count = send(fd_, &buf[idx], remSize, MSG_DONTWAIT | MSG_NOSIGNAL);
80c29fa5a6Sopenharmony_ci        if (count < 0) {
81c29fa5a6Sopenharmony_ci            if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
82c29fa5a6Sopenharmony_ci                usleep(SEND_RETRY_SLEEP_TIME);
83c29fa5a6Sopenharmony_ci                FI_HILOGW("Continue for errno EAGAIN|EINTR|EWOULDBLOCK, errno:%{public}d, pid:%{public}d", errno, pid_);
84c29fa5a6Sopenharmony_ci                continue;
85c29fa5a6Sopenharmony_ci            }
86c29fa5a6Sopenharmony_ci            FI_HILOGE("Send return failed, error:%{public}d, fd:%{public}d, pid:%{public}d", errno, fd_, pid_);
87c29fa5a6Sopenharmony_ci            return false;
88c29fa5a6Sopenharmony_ci        }
89c29fa5a6Sopenharmony_ci        idx += count;
90c29fa5a6Sopenharmony_ci        remSize -= count;
91c29fa5a6Sopenharmony_ci        if (remSize > 0) {
92c29fa5a6Sopenharmony_ci            usleep(SEND_RETRY_SLEEP_TIME);
93c29fa5a6Sopenharmony_ci        }
94c29fa5a6Sopenharmony_ci    }
95c29fa5a6Sopenharmony_ci    if (retryCount >= SEND_RETRY_LIMIT || remSize != 0) {
96c29fa5a6Sopenharmony_ci        FI_HILOGE("Send too many times:%{public}d/%{public}d, size:%{public}d/%{public}d, fd:%{public}d,"
97c29fa5a6Sopenharmony_ci            "pid:%{public}d", retryCount, SEND_RETRY_LIMIT, idx, bufSize, fd_, pid_);
98c29fa5a6Sopenharmony_ci        return false;
99c29fa5a6Sopenharmony_ci    }
100c29fa5a6Sopenharmony_ci    return true;
101c29fa5a6Sopenharmony_ci}
102c29fa5a6Sopenharmony_ci
103c29fa5a6Sopenharmony_cistd::string SocketSession::ToString() const
104c29fa5a6Sopenharmony_ci{
105c29fa5a6Sopenharmony_ci    std::ostringstream oss;
106c29fa5a6Sopenharmony_ci    oss << "fd = " << fd_
107c29fa5a6Sopenharmony_ci        << ((fd_ < 0) ? ", closed" : ", opened")
108c29fa5a6Sopenharmony_ci        << ", pid = " << pid_
109c29fa5a6Sopenharmony_ci        << ", tokenType = " << tokenType_
110c29fa5a6Sopenharmony_ci        << std::endl;
111c29fa5a6Sopenharmony_ci    return oss.str();
112c29fa5a6Sopenharmony_ci}
113c29fa5a6Sopenharmony_ci
114c29fa5a6Sopenharmony_civoid SocketSession::Dispatch(const struct epoll_event &ev)
115c29fa5a6Sopenharmony_ci{
116c29fa5a6Sopenharmony_ci    if ((ev.events & EPOLLIN) == EPOLLIN) {
117c29fa5a6Sopenharmony_ci        FI_HILOGD("Data received (%{public}d)", fd_);
118c29fa5a6Sopenharmony_ci    } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
119c29fa5a6Sopenharmony_ci        FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
120c29fa5a6Sopenharmony_ci    }
121c29fa5a6Sopenharmony_ci}
122c29fa5a6Sopenharmony_ci} // namespace DeviceStatus
123c29fa5a6Sopenharmony_ci} // namespace Msdp
124c29fa5a6Sopenharmony_ci} // namespace OHOS