1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 "tcp_server.h"
17 #include <arpa/inet.h>
18 #include "common/media_log.h"
19 #include "network/session/tcp_session.h"
20 #include "network/socket/socket_utils.h"
21 #include "network/socket/tcp_socket.h"
22 #include "utils/utils.h"
23 namespace OHOS {
24 namespace Sharing {
~TcpServer()25 TcpServer::~TcpServer()
26 {
27 SHARING_LOGD("trace.");
28 Stop();
29 }
30
TcpServer()31 TcpServer::TcpServer()
32 {
33 SHARING_LOGD("trace.");
34 }
35
Start(uint16_t port,const std::string & host,bool enableReuse,uint32_t backlog)36 bool TcpServer::Start(uint16_t port, const std::string &host, bool enableReuse, uint32_t backlog)
37 {
38 SHARING_LOGD("server ip:%{public}s, Port:%{public}d, thread_id: %{public}llu.",
39 GetAnonymousIp(host).c_str(), port, GetThreadId());
40 socket_ = std::make_unique<TcpSocket>();
41 if (socket_) {
42 if (socket_->Bind(port, host, enableReuse, backlog)) {
43 SHARING_LOGD("start success fd: %{public}d.", socket_->GetLocalFd());
44 socketLocalFd_ = socket_->GetLocalFd();
45
46 auto eventRunner = OHOS::AppExecFwk::EventRunner::Create(true);
47 eventHandler_ = std::make_shared<TcpServerEventHandler>();
48 eventHandler_->SetServer(shared_from_this());
49 eventHandler_->SetEventRunner(eventRunner);
50 eventRunner->Run();
51
52 eventListener_ = std::make_shared<TcpServerEventListener>();
53 eventListener_->SetServer(shared_from_this());
54
55 return eventListener_->AddFdListener(socket_->GetLocalFd(), eventListener_, eventHandler_);
56 }
57 }
58
59 SHARING_LOGE("start failed!");
60 return false;
61 }
62
Stop()63 void TcpServer::Stop()
64 {
65 SHARING_LOGD("trace.");
66 std::unique_lock<std::shared_mutex> lk(mutex_);
67 if (socket_ != nullptr) {
68 if (eventListener_) {
69 eventListener_->RemoveFdListener(socket_->GetLocalFd());
70 }
71 SocketUtils::ShutDownSocket(socket_->GetLocalFd());
72 SocketUtils::CloseSocket(socket_->GetLocalFd());
73 for (auto it = sessions_.begin(); it != sessions_.end(); it++) {
74 SHARING_LOGD("closeClientSocket:erase fd: %{public}d,size: %{public}zu.", it->first, sessions_.size());
75 if (it->second) {
76 it->second->Shutdown();
77 it->second.reset();
78 }
79 }
80 sessions_.clear();
81 socket_.reset();
82 }
83 }
84
CloseClientSocket(int32_t fd)85 void TcpServer::CloseClientSocket(int32_t fd)
86 {
87 SHARING_LOGD("fd: %{public}d.", fd);
88 if (fd > 0) {
89 auto itemItr = sessions_.find(fd);
90 if (itemItr != sessions_.end()) {
91 if (itemItr->second) {
92 itemItr->second->Shutdown();
93 itemItr->second.reset();
94 }
95 sessions_.erase(itemItr);
96 SHARING_LOGD("erase fd: %{public}d.", fd);
97 }
98 }
99 }
100
GetSocketInfo()101 SocketInfo::Ptr TcpServer::GetSocketInfo()
102 {
103 SHARING_LOGD("trace.");
104 return socket_;
105 }
106
SetClientFd(int32_t clientFd)107 void TcpServer::SetClientFd(int32_t clientFd)
108 {
109 SocketUtils::SetNonBlocking(clientFd);
110 SocketUtils::SetNoDelay(clientFd, true);
111 SocketUtils::SetSendBuf(clientFd);
112 SocketUtils::SetRecvBuf(clientFd);
113 SocketUtils::SetCloseWait(clientFd);
114 SocketUtils::SetCloExec(clientFd, true);
115 SocketUtils::SetKeepAlive(clientFd);
116 int32_t value = 0xBC;
117 setsockopt(clientFd, IPPROTO_IP, IP_TOS, &value, sizeof(value));
118 }
119
OnServerReadable(int32_t fd)120 void TcpServer::OnServerReadable(int32_t fd)
121 {
122 SHARING_LOGD("fd: %{public}d, socketLocalFd: %{public}d, thread_id: %{public}llu.", fd, socketLocalFd_,
123 GetThreadId());
124 std::unique_lock<std::shared_mutex> lk(mutex_);
125 struct sockaddr_in clientAddr;
126 socklen_t addrLen = sizeof(sockaddr_in);
127 if (fd == socketLocalFd_) {
128 int32_t clientFd = SocketUtils::AcceptSocket(fd, &clientAddr, &addrLen);
129 if (clientFd < 0) {
130 SHARING_LOGE("onReadable accept client error!");
131 return;
132 }
133 SetClientFd(clientFd);
134 SHARING_LOGD("onReadable accept client fd: %{public}d.", clientFd);
135 if (socket_) {
136 socket_->socketPeerFd_ = clientFd;
137
138 std::string strLocalAddr = "";
139 std::string strRemoteAddr = "";
140 uint16_t localPort = 0;
141 uint16_t remotePort = 0;
142 SocketUtils::GetIpPortInfo(clientFd, strLocalAddr, strRemoteAddr, localPort, remotePort);
143
144 SocketInfo::Ptr socketInfo =
145 std::make_shared<SocketInfo>(strLocalAddr, strRemoteAddr, fd, clientFd, localPort, remotePort);
146 if (socketInfo) {
147 socketInfo->SetSocketType(SOCKET_TYPE_TCP);
148 BaseNetworkSession::Ptr session = std::make_shared<TcpSession>(std::move(socketInfo));
149 if (session) {
150 MEDIA_LOGE("[TcpServer] OnReadable new session start.");
151 sessions_.insert(make_pair(clientFd, std::move(session)));
152 auto callback = callback_.lock();
153 if (callback) {
154 callback->OnAccept(sessions_[clientFd]);
155 }
156 } else {
157 MEDIA_LOGE("onReadable create session failed!");
158 }
159 } else {
160 MEDIA_LOGE("onReadable create SocketInfo failed!");
161 }
162 }
163 } else {
164 MEDIA_LOGD("onReadable receive msg!");
165 }
166 }
167 } // namespace Sharing
168 } // namespace OHOS