1/* 2 * Copyright (c) 2021-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_session.h" 17 18#include <cinttypes> 19#include <sstream> 20 21#include <fcntl.h> 22#include <sys/types.h> 23#include <sys/un.h> 24#include <unistd.h> 25 26#include "stream_socket.h" 27#include "proto.h" 28 29#undef LOG_TAG 30#define LOG_TAG "StreamSession" 31 32namespace OHOS { 33namespace Msdp { 34namespace DeviceStatus { 35namespace { 36const std::string FOUNDATION { "foundation" }; 37} // namespace 38 39StreamSession::StreamSession(const std::string &programName, int32_t moduleType, int32_t fd, int32_t uid, int32_t pid) 40 : fd_(fd), pid_(pid) 41{} 42 43bool StreamSession::SendMsg(const char *buf, size_t size) const 44{ 45 CHKPF(buf); 46 if ((size == 0) || (size > MAX_PACKET_BUF_SIZE)) { 47 FI_HILOGE("buf size:%{public}zu", size); 48 return false; 49 } 50 if (fd_ < 0) { 51 FI_HILOGE("The fd_ is less than 0"); 52 return false; 53 } 54 55 int32_t idx = 0; 56 int32_t retryCount = 0; 57 const int32_t bufSize = static_cast<int32_t>(size); 58 int32_t remSize = bufSize; 59 while (remSize > 0 && retryCount < SEND_RETRY_LIMIT) { 60 retryCount += 1; 61 ssize_t count = send(fd_, &buf[idx], remSize, MSG_DONTWAIT | MSG_NOSIGNAL); 62 if (count < 0) { 63 if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) { 64 usleep(SEND_RETRY_SLEEP_TIME); 65 FI_HILOGW("Continue for errno EAGAIN|EINTR|EWOULDBLOCK, errno:%{public}d", errno); 66 continue; 67 } 68 FI_HILOGE("Send return failed, error:%{public}d, fd:%{public}d", errno, fd_); 69 return false; 70 } 71 idx += count; 72 remSize -= count; 73 if (remSize > 0) { 74 usleep(SEND_RETRY_SLEEP_TIME); 75 } 76 } 77 if (retryCount >= SEND_RETRY_LIMIT || remSize != 0) { 78 FI_HILOGE("Send too many times:%{public}d/%{public}d, size:%{public}d/%{public}d, fd:%{public}d", 79 retryCount, SEND_RETRY_LIMIT, idx, bufSize, fd_); 80 return false; 81 } 82 return true; 83} 84 85void StreamSession::Close() 86{ 87 CALL_DEBUG_ENTER; 88 FI_HILOGD("Enter fd_:%{public}d", fd_); 89 if (fd_ >= 0) { 90 if (close(fd_) < 0) { 91 FI_HILOGE("Close fd failed, error:%{public}s, fd_:%{public}d", strerror(errno), fd_); 92 } 93 fd_ = -1; 94 } 95} 96 97bool StreamSession::SendMsg(NetPacket &pkt) const 98{ 99 if (pkt.ChkRWError()) { 100 FI_HILOGE("Read and write status is error"); 101 return false; 102 } 103 StreamBuffer buf; 104 if (!pkt.MakeData(buf)) { 105 FI_HILOGE("Failed to buffer packet"); 106 return false; 107 } 108 return SendMsg(buf.Data(), buf.Size()); 109} 110} // namespace DeviceStatus 111} // namespace Msdp 112} // namespace OHOS