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#undef LOG_TAG 26#define LOG_TAG "SocketSession" 27 28namespace OHOS { 29namespace Msdp { 30namespace DeviceStatus { 31 32SocketSession::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), programName_(programName) 35{} 36 37SocketSession::~SocketSession() 38{ 39 if ((fd_ >= 0) && (::close(fd_) != 0)) { 40 FI_HILOGE("close(%{public}d) failed:%{public}s", fd_, ::strerror(errno)); 41 } 42} 43 44bool 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 if (!pkt.MakeData(buf)) { 52 FI_HILOGE("Failed to buffer packet"); 53 return false; 54 } 55 return SendMsg(buf.Data(), buf.Size()); 56} 57 58bool SocketSession::SendMsg(const char *buf, size_t size) const 59{ 60 CHKPF(buf); 61 if ((size == 0) || (size > MAX_PACKET_BUF_SIZE)) { 62 FI_HILOGE("buf size:%{public}zu", size); 63 return false; 64 } 65 if (fd_ < 0) { 66 FI_HILOGE("The fd_ is less than 0"); 67 return false; 68 } 69 70 int32_t idx = 0; 71 int32_t retryCount = 0; 72 const int32_t bufSize = static_cast<int32_t>(size); 73 int32_t remSize = bufSize; 74 FI_HILOGD("Rem size:%{public}d", remSize); 75 while (remSize > 0 && retryCount < SEND_RETRY_LIMIT) { 76 retryCount += 1; 77 FI_HILOGD("Send message to client (%{public}d, %{public}d)", fd_, pid_); 78 ssize_t count = send(fd_, &buf[idx], remSize, MSG_DONTWAIT | MSG_NOSIGNAL); 79 if (count < 0) { 80 if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) { 81 usleep(SEND_RETRY_SLEEP_TIME); 82 FI_HILOGW("Continue for errno EAGAIN|EINTR|EWOULDBLOCK, errno:%{public}d, pid:%{public}d", errno, pid_); 83 continue; 84 } 85 FI_HILOGE("Send return failed, error:%{public}d, fd:%{public}d, pid:%{public}d", errno, fd_, pid_); 86 return false; 87 } 88 idx += count; 89 remSize -= count; 90 if (remSize > 0) { 91 usleep(SEND_RETRY_SLEEP_TIME); 92 } 93 } 94 if (retryCount >= SEND_RETRY_LIMIT || remSize != 0) { 95 FI_HILOGE("Send too many times:%{public}d/%{public}d, size:%{public}d/%{public}d, fd:%{public}d," 96 "pid:%{public}d", retryCount, SEND_RETRY_LIMIT, idx, bufSize, fd_, pid_); 97 return false; 98 } 99 return true; 100} 101 102std::string SocketSession::ToString() const 103{ 104 std::ostringstream oss; 105 oss << "fd = " << fd_ 106 << ((fd_ < 0) ? ", closed" : ", opened") 107 << ", pid = " << pid_ 108 << ", tokenType = " << tokenType_ 109 << std::endl; 110 return oss.str(); 111} 112 113void SocketSession::Dispatch(const struct epoll_event &ev) 114{ 115 if ((ev.events & EPOLLIN) == EPOLLIN) { 116 FI_HILOGD("Data received (%{public}d)", fd_); 117 } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) { 118 FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno)); 119 } 120} 121} // namespace DeviceStatus 122} // namespace Msdp 123} // namespace OHOS