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