1 /*
2 * Copyright (c) 2021 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 "appspawn_socket.h"
17
18 #include <cerrno>
19 #include <iostream>
20 #include <sys/socket.h>
21
22 #include "hilog/log.h"
23 #include "pubdef.h"
24 #include "securec.h"
25
26 namespace OHOS {
27 namespace AppSpawn {
28 using namespace OHOS::HiviewDFX;
29 static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "AppSpawnSocket"};
30
AppSpawnSocket(const std::string & name)31 AppSpawnSocket::AppSpawnSocket(const std::string &name)
32 {
33 socketName_ = name;
34 }
35
~AppSpawnSocket()36 AppSpawnSocket::~AppSpawnSocket()
37 {
38 if (socketFd_ > 0) {
39 CloseSocket(socketFd_);
40 socketFd_ = -1;
41 }
42 }
43
GetSocketFd() const44 int AppSpawnSocket::GetSocketFd() const
45 {
46 return socketFd_;
47 }
48
PackSocketAddr()49 int AppSpawnSocket::PackSocketAddr()
50 {
51 if (socketName_.empty()) {
52 HiLog::Error(LABEL, "Invalid socket name: empty");
53 return -EINVAL;
54 }
55
56 if (memset_s(&socketAddr_, sizeof(socketAddr_), 0, sizeof(socketAddr_)) != EOK) {
57 HiLog::Error(LABEL, "Failed to memset socket addr");
58 return -1;
59 }
60
61 socklen_t pathLen = 0;
62 if (socketName_[0] == '/') {
63 pathLen = socketName_.length();
64 } else {
65 pathLen = socketDir_.length() + socketName_.length();
66 }
67 socklen_t pathSize = sizeof(socketAddr_.sun_path);
68 if (pathLen >= pathSize) {
69 HiLog::Error(LABEL, "Invalid socket name: '%s' too long", socketName_.c_str());
70 return -1;
71 }
72
73 int len = 0;
74 if (socketName_[0] == '/') {
75 len = snprintf_s(socketAddr_.sun_path, pathSize, (pathSize - 1), "%s", socketName_.c_str());
76 } else {
77 len = snprintf_s(socketAddr_.sun_path, pathSize, (pathSize - 1), "%s%s",
78 socketDir_.c_str(), socketName_.c_str());
79 }
80 if (static_cast<int>(pathLen) != len) {
81 HiLog::Error(LABEL, "Failed to copy socket path");
82 return -1;
83 }
84
85 socketAddr_.sun_family = AF_LOCAL;
86 socketAddrLen_ = offsetof(struct sockaddr_un, sun_path) + pathLen + 1;
87
88 return 0;
89 }
90
CreateSocket()91 int AppSpawnSocket::CreateSocket()
92 {
93 int socketFd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
94 if (socketFd < 0) {
95 HiLog::Error(LABEL, "Failed to create socket: %d", errno);
96 return (-errno);
97 }
98
99 HiLog::Debug(LABEL, "Created socket with fd %d", socketFd);
100 return socketFd;
101 }
102
CloseSocket(int & socketFd)103 void AppSpawnSocket::CloseSocket(int &socketFd)
104 {
105 if (socketFd >= 0) {
106 HiLog::Debug(LABEL, "Closed socket with fd %d", socketFd);
107 close(socketFd);
108 socketFd = -1;
109 }
110 }
111
ReadSocketMessage(int socketFd,void * buf,int len)112 int AppSpawnSocket::ReadSocketMessage(int socketFd, void *buf, int len)
113 {
114 if (socketFd < 0 || len <= 0 || buf == nullptr) {
115 HiLog::Error(LABEL, "Invalid args: socket %d, len %d, buf might be nullptr", socketFd, len);
116 return -1;
117 }
118
119 if (memset_s(buf, len, 0, len) != EOK) {
120 HiLog::Warn(LABEL, "Failed to memset read buf");
121 return -1;
122 }
123
124 ssize_t rLen = TEMP_FAILURE_RETRY(read(socketFd, buf, len));
125 if (rLen < 0) {
126 HiLog::Error(LABEL, "Read message from fd %d error %zd: %d", socketFd, rLen, errno);
127 return -EFAULT;
128 }
129
130 return rLen;
131 }
132
WriteSocketMessage(int socketFd,const void * buf,int len)133 int AppSpawnSocket::WriteSocketMessage(int socketFd, const void *buf, int len)
134 {
135 if (socketFd < 0 || len <= 0 || buf == nullptr) {
136 HiLog::Error(LABEL, "Invalid args: socket %d, len %d, buf might be nullptr", socketFd, len);
137 return -1;
138 }
139
140 ssize_t written = 0;
141 ssize_t remain = static_cast<ssize_t>(len);
142 const uint8_t *offset = reinterpret_cast<const uint8_t *>(buf);
143 for (ssize_t wLen = 0; remain > 0; offset += wLen, remain -= wLen, written += wLen) {
144 wLen = write(socketFd, offset, remain);
145 HiLog::Debug(LABEL, "socket fd %d, wLen %zd", socketFd, wLen);
146 if ((wLen <= 0) && (errno != EINTR)) {
147 HiLog::Error(LABEL, "Failed to write message to fd %d, error %zd: %d", socketFd, wLen, errno);
148 return (-errno);
149 }
150 }
151
152 return written;
153 }
154 } // namespace AppSpawn
155 } // namespace OHOS
156