• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <linux/tcp.h>
20 #include <linux/in.h>
21 #include <cerrno>
22 
23 #include "appspawn_server.h"
24 #include "pubdef.h"
25 #include "securec.h"
26 
27 namespace OHOS {
28 namespace AppSpawn {
AppSpawnSocket(const std::string & name)29 AppSpawnSocket::AppSpawnSocket(const std::string &name)
30 {
31     socketName_ = name;
32 }
33 
~AppSpawnSocket()34 AppSpawnSocket::~AppSpawnSocket()
35 {
36     if (socketFd_ > 0) {
37         CloseSocket(socketFd_);
38         socketFd_ = -1;
39     }
40 }
41 
GetSocketFd() const42 int AppSpawnSocket::GetSocketFd() const
43 {
44     return socketFd_;
45 }
46 
PackSocketAddr()47 int AppSpawnSocket::PackSocketAddr()
48 {
49     APPSPAWN_CHECK(!socketName_.empty(), return -EINVAL, "Invalid socket name: empty");
50     (void)memset_s(&socketAddr_, sizeof(socketAddr_), 0, sizeof(socketAddr_));
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: '%{public}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: %{public}d", errno);
83 
84     int flag = 1;
85     int ret = setsockopt(socketFd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
86     APPSPAWN_LOGV("Created socket with fd %{public}d, setsockopt %{public}d", socketFd, ret);
87     return socketFd;
88 }
89 
CloseSocket(int & socketFd)90 void AppSpawnSocket::CloseSocket(int &socketFd)
91 {
92     if (socketFd >= 0) {
93         APPSPAWN_LOGV("Closed socket with fd %{public}d", socketFd);
94         int flag = 0;
95         setsockopt(socketFd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
96         close(socketFd);
97         socketFd = -1;
98     }
99 }
100 
ReadSocketMessage(int socketFd,void * buf,int len)101 int AppSpawnSocket::ReadSocketMessage(int socketFd, void *buf, int len)
102 {
103     if (socketFd < 0 || len <= 0 || buf == nullptr) {
104         APPSPAWN_LOGE("Invalid args: socket %{public}d, len %{public}d, buf might be nullptr", socketFd, len);
105         return -1;
106     }
107 
108     APPSPAWN_CHECK(memset_s(buf, len, 0, len) == EOK, return -1, "Failed to memset read buf");
109 
110     ssize_t rLen = TEMP_FAILURE_RETRY(read(socketFd, buf, len));
111     while ((rLen < 0) && (errno == EAGAIN)) {
112         rLen = TEMP_FAILURE_RETRY(read(socketFd, buf, len));
113     }
114     APPSPAWN_CHECK(rLen >= 0, return -EFAULT,
115         "Read message from fd %{public}d error %{public}zd: %{public}d", socketFd, rLen, errno);
116 
117     return rLen;
118 }
119 
WriteSocketMessage(int socketFd,const void * buf,int len)120 int AppSpawnSocket::WriteSocketMessage(int socketFd, const void *buf, int len)
121 {
122     if (socketFd < 0 || len <= 0 || buf == nullptr) {
123         APPSPAWN_LOGE("Invalid args: socket %{public}d, len %{public}d, buf might be nullptr", socketFd, len);
124         return -1;
125     }
126 
127     ssize_t written = 0;
128     ssize_t remain = static_cast<ssize_t>(len);
129     const uint8_t *offset = reinterpret_cast<const uint8_t *>(buf);
130     for (ssize_t wLen = 0; remain > 0; offset += wLen, remain -= wLen, written += wLen) {
131         wLen = write(socketFd, offset, remain);
132         APPSPAWN_LOGV("socket fd %{public}d, wLen %{public}zd", socketFd, wLen);
133         bool isRet = (wLen <= 0) && (errno != EINTR);
134         APPSPAWN_CHECK(!isRet, return -errno,
135             "Failed to write message to fd %{public}d, error %{public}zd: %{public}d", socketFd, wLen, errno);
136     }
137 
138     return written;
139 }
140 }  // namespace AppSpawn
141 }  // namespace OHOS
142