• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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  * Description: tcp socket.
15  * Author: renshuang
16  * Create: 2023-09-25
17  */
18 
19 #include "tcp_socket.h"
20 
21 #include "cast_engine_log.h"
22 #include "securec.h"
23 
24 namespace OHOS {
25 namespace CastEngine {
26 namespace CastEngineService {
27 DEFINE_CAST_ENGINE_LABEL("CastEngine-TcpSocket");
28 
TcpSocket()29 TcpSocket::TcpSocket()
30 {
31     socket_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
32     if (socket_ < RET_OK) {
33         CLOGE("Create socket error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
34     } else {
35         CLOGD("Create socket success.");
36     }
37 }
38 
~TcpSocket()39 TcpSocket::~TcpSocket()
40 {
41     Close();
42 }
43 
Bind(const std::string & ip,int port)44 int TcpSocket::Bind(const std::string &ip, int port)
45 {
46     struct sockaddr_in sockaddr{};
47     sockaddr.sin_family = AF_INET;
48     if (ip.empty()) {
49         sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
50     } else {
51         sockaddr.sin_addr.s_addr = inet_addr(ip.c_str());
52     }
53     if (port == INVALID_PORT) {
54         sockaddr.sin_port = htons(RANDOM_PORT);
55     } else {
56         sockaddr.sin_port = htons(port);
57     }
58     if (::bind(socket_, reinterpret_cast<struct sockaddr *>(&sockaddr), sizeof(sockaddr)) < RET_OK) {
59         CLOGE("Socket bind error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
60         return INVALID_PORT;
61     }
62     CLOGD("Socket bind success.");
63     if (port == INVALID_PORT) {
64         return GetBindPort();
65     }
66     return port;
67 }
68 
GetBindPort()69 int TcpSocket::GetBindPort()
70 {
71     if (socket_ == INVALID_SOCKET) {
72         CLOGE("Socket getBindPort error: socket_ is invalid");
73         return INVALID_PORT;
74     }
75     struct sockaddr_in sockaddr{};
76     socklen_t addrLen = sizeof(sockaddr);
77     if (getsockname(socket_, reinterpret_cast<struct sockaddr *>(&sockaddr), &addrLen) < RET_OK) {
78         CLOGE("Socket getBindPort error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
79         return INVALID_PORT;
80     }
81     return ntohs(sockaddr.sin_port);
82 }
83 
GetPeerPort(int fd)84 int TcpSocket::GetPeerPort(int fd)
85 {
86     if (fd == INVALID_SOCKET) {
87         CLOGE("Socket getPeerPort error: socket is invalid");
88         return INVALID_PORT;
89     }
90     struct sockaddr_in sockaddr{};
91     socklen_t addrLen = sizeof(sockaddr);
92     if (getpeername(fd, reinterpret_cast<struct sockaddr *>(&sockaddr), &addrLen) < RET_OK) {
93         CLOGE("Socket getPeerPort error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
94         return INVALID_PORT;
95     }
96     return ntohs(sockaddr.sin_port);
97 }
98 
GetSocketFd()99 int TcpSocket::GetSocketFd()
100 {
101     return socket_;
102 }
103 
Listen(int backlog)104 bool TcpSocket::Listen(int backlog)
105 {
106     if (::listen(socket_, backlog) < RET_OK) {
107         CLOGE("Socket listen error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
108         return false;
109     }
110     CLOGD("Socket listening...");
111     return true;
112 }
113 
Connect(const std::string & ip,int port)114 bool TcpSocket::Connect(const std::string & ip, int port)
115 {
116     struct sockaddr_in sockaddr{};
117     sockaddr.sin_family = AF_INET;
118     sockaddr.sin_addr.s_addr = inet_addr(ip.c_str());
119     sockaddr.sin_port = htons(port);
120     if (::connect(socket_, reinterpret_cast<struct sockaddr *>(&sockaddr), sizeof(sockaddr)) < RET_OK) {
121         CLOGE("Socket connect error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
122         return false;
123     }
124     CLOGD("Socket connect success.");
125     return true;
126 }
127 
Accept()128 int TcpSocket::Accept()
129 {
130     int connfd = ::accept(socket_, nullptr, nullptr);
131     if (connfd < RET_OK) {
132         CLOGE("Socket accept error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
133         return INVALID_SOCKET;
134     }
135     CLOGD("Socket accept success.");
136     return connfd;
137 }
138 
Send(int fd,const uint8_t * buff,size_t length)139 int TcpSocket::Send(int fd, const uint8_t *buff, size_t length)
140 {
141     auto ret = ::send(fd, buff, length, SOCKET_FLAG);
142     if (ret < RET_OK) {
143         CLOGE("Socket send error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
144     }
145     return ret;
146 }
147 
Recv(int fd,uint8_t * buff,size_t length)148 ssize_t TcpSocket::Recv(int fd, uint8_t *buff, size_t length)
149 {
150     size_t recvLen = 0;
151     while (recvLen < length) {
152         ssize_t len;
153         int error;
154         do {
155             len = ::recv(fd, buff + recvLen, length - recvLen, SOCKET_FLAG);
156             error = errno;
157             if (stopReceive_) {
158                 return STOP_RECEIVE;
159             }
160         } while (len <= 0 && (error == EINTR || error == EAGAIN));
161 
162         if (len < RET_OK) {
163             CLOGE("Socket recv error: errno = %{public}d, errmsg = %{public}s.", error, strerror(error));
164             return RET_ERR;
165         }
166 
167         recvLen += static_cast<size_t>(len);
168     }
169 
170     CLOGD("Socket recv DONE!, size:%zu", recvLen);
171     return recvLen;
172 }
173 
Close()174 void TcpSocket::Close()
175 {
176     if (socket_ > INVALID_SOCKET) {
177         ::close(socket_);
178         socket_ = INVALID_SOCKET;
179     }
180 }
181 
Shutdown(int fd)182 void TcpSocket::Shutdown(int fd)
183 {
184     if (fd > INVALID_SOCKET) {
185         stopReceive_ = true;
186         ::shutdown((fd), SHUT_RDWR);
187     }
188 }
189 
SetSendBufferSize(int size)190 bool TcpSocket::SetSendBufferSize(int size)
191 {
192     int buffSize = size;
193     if (setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, &buffSize, sizeof(buffSize)) < RET_OK) {
194         CLOGE("Socket SetSendBufferSize error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
195         return false;
196     }
197     CLOGD("Socket SetSendBufferSize success.");
198     return true;
199 }
200 
SetRecvBufferSize(int size)201 bool TcpSocket::SetRecvBufferSize(int size)
202 {
203     int buffSize = size;
204     if (setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, &buffSize, sizeof(buffSize)) < RET_OK) {
205         CLOGE("Socket SetRecvBufferSize error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
206         return false;
207     }
208     CLOGD("Socket SetRecvBufferSize success.");
209     return true;
210 }
211 
SetLinger(bool active,int seconds)212 bool TcpSocket::SetLinger(bool active, int seconds)
213 {
214     struct linger lgr{};
215     lgr.l_onoff = active ? SOCKET_ON : SOCKET_OFF;
216     lgr.l_linger = seconds;
217     if (setsockopt(socket_, SOL_SOCKET, SO_LINGER, &lgr, sizeof(lgr)) < RET_OK) {
218         CLOGE("Socket SetLinger error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
219         return false;
220     }
221     CLOGD("Socket SetLinger success.");
222     return true;
223 }
224 
SetKeepAlive()225 bool TcpSocket::SetKeepAlive()
226 {
227     return SetKeepAlive(DEFAULT_VALUE, DEFAULT_VALUE, DEFAULT_VALUE);
228 }
229 
SetKeepAlive(unsigned idleTime,unsigned numProbes,unsigned probeInterval)230 bool TcpSocket::SetKeepAlive(unsigned idleTime, unsigned numProbes, unsigned probeInterval)
231 {
232     int flag = SOCKET_ON;
233     if (setsockopt(socket_, SOL_SOCKET, SO_KEEPALIVE, &flag, sizeof(flag)) < RET_OK) {
234         CLOGE("Socket SetKeepAlive error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
235         return false;
236     }
237     if (idleTime != DEFAULT_VALUE) {
238         if (setsockopt(socket_, SOL_TCP, TCP_KEEPIDLE, &idleTime, sizeof(idleTime)) < RET_OK) {
239             CLOGE("Socket SetKeepIDLE error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
240             return false;
241         }
242     }
243     if (numProbes != DEFAULT_VALUE) {
244         if (setsockopt(socket_, SOL_TCP, TCP_KEEPCNT, &numProbes, sizeof(numProbes)) < RET_OK) {
245             CLOGE("Socket SetKeepCNT error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
246             return false;
247         }
248     }
249     if (probeInterval != DEFAULT_VALUE) {
250         if (setsockopt(socket_, SOL_TCP, TCP_KEEPINTVL, &probeInterval, sizeof(probeInterval)) < RET_OK) {
251             CLOGE("Socket SetKeepINTVL error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
252             return false;
253         }
254     }
255     CLOGD("Socket SetKeepAlive success.");
256     return true;
257 }
258 
SetReuseAddr()259 bool TcpSocket::SetReuseAddr()
260 {
261     int flag = SOCKET_ON;
262     if (setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) < RET_OK) {
263         CLOGE("Socket SetReuseAddr error: errno = %{public}d, errmsg = %{public}s.", errno, strerror(errno));
264         return false;
265     }
266     CLOGD("Socket SetReuseAddr success.");
267     return true;
268 }
269 
270 } // namespace CastEngineService
271 } // namespace CastEngine
272 } // namespace OHOS