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 "socket_session.h"
17
18 #include <sstream>
19
20 #include <sys/socket.h>
21 #include <unistd.h>
22
23 #include "proto.h"
24
25 namespace OHOS {
26 namespace Msdp {
27 namespace DeviceStatus {
28 namespace {
29 constexpr OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "SocketSession" };
30 } // namespace
31
SocketSession(const std::string & programName,int32_t moduleType,int32_t tokenType,int32_t fd,int32_t uid,int32_t pid)32 SocketSession::SocketSession(const std::string &programName, int32_t moduleType,
33 int32_t tokenType, int32_t fd, int32_t uid, int32_t pid)
34 : fd_(fd), uid_(uid), pid_(pid), tokenType_(tokenType)
35 {}
36
~SocketSession()37 SocketSession::~SocketSession()
38 {
39 if ((fd_ >= 0) && (::close(fd_) != 0)) {
40 FI_HILOGE("close(%{public}d) failed:%{public}s", fd_, ::strerror(errno));
41 }
42 }
43
SendMsg(NetPacket & pkt) const44 bool SocketSession::SendMsg(NetPacket &pkt) const
45 {
46 if (pkt.ChkRWError()) {
47 FI_HILOGE("Read and write status is error");
48 return false;
49 }
50 StreamBuffer buf;
51 pkt.MakeData(buf);
52 return SendMsg(buf.Data(), buf.Size());
53 }
54
SendMsg(const char * buf,size_t size) const55 bool SocketSession::SendMsg(const char *buf, size_t size) const
56 {
57 CHKPF(buf);
58 if ((size == 0) || (size > MAX_PACKET_BUF_SIZE)) {
59 FI_HILOGE("buf size:%{public}zu", size);
60 return false;
61 }
62 if (fd_ < 0) {
63 FI_HILOGE("The fd_ is less than 0");
64 return false;
65 }
66
67 int32_t idx = 0;
68 int32_t retryCount = 0;
69 const int32_t bufSize = static_cast<int32_t>(size);
70 int32_t remSize = bufSize;
71 while (remSize > 0 && retryCount < SEND_RETRY_LIMIT) {
72 retryCount += 1;
73 ssize_t count = send(fd_, &buf[idx], remSize, MSG_DONTWAIT | MSG_NOSIGNAL);
74 if (count < 0) {
75 if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
76 usleep(SEND_RETRY_SLEEP_TIME);
77 FI_HILOGW("Continue for errno EAGAIN|EINTR|EWOULDBLOCK, errno:%{public}d", errno);
78 continue;
79 }
80 FI_HILOGE("Send return failed, error:%{public}d, fd:%{public}d", errno, fd_);
81 return false;
82 }
83 idx += count;
84 remSize -= count;
85 if (remSize > 0) {
86 usleep(SEND_RETRY_SLEEP_TIME);
87 }
88 }
89 if (retryCount >= SEND_RETRY_LIMIT || remSize != 0) {
90 FI_HILOGE("Send too many times:%{public}d/%{public}d, size:%{public}d/%{public}d, fd:%{public}d",
91 retryCount, SEND_RETRY_LIMIT, idx, bufSize, fd_);
92 return false;
93 }
94 return true;
95 }
96
ToString() const97 std::string SocketSession::ToString() const
98 {
99 std::ostringstream oss;
100 oss << "fd = " << fd_
101 << ((fd_ < 0) ? ", closed" : ", opened")
102 << ", pid = " << pid_
103 << ", tokenType = " << tokenType_
104 << std::endl;
105 return oss.str();
106 }
107
Dispatch(const struct epoll_event & ev)108 void SocketSession::Dispatch(const struct epoll_event &ev)
109 {
110 if ((ev.events & EPOLLIN) == EPOLLIN) {
111 FI_HILOGD("Data received (%{public}d)", fd_);
112 } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
113 FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
114 }
115 }
116 } // namespace DeviceStatus
117 } // namespace Msdp
118 } // namespace OHOS