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 "http_socket.h"
17 #include <cstring>
18 #ifdef _WIN32
19 #include <WinSock2.h>
20 #include <Ws2tcpip.h>
21 #else
22 #include <netinet/in.h>
23 #include <sys/socket.h>
24 #include <unistd.h>
25 #endif
26 #include "log.h"
27 namespace SysTuning {
28 namespace TraceStreamer {
~HttpSocket()29 HttpSocket::~HttpSocket()
30 {
31 Close();
32 }
CreateSocket(int domain)33 bool HttpSocket::CreateSocket(int domain)
34 {
35 SOCKET sockId = socket(domain, SOCK_STREAM, 0);
36 if (sockId == INVALID_SOCKET) {
37 TS_LOGE("CreateSocket socket error, domain %d: %d:%s", domain, errno, strerror(errno));
38 return false;
39 }
40 sockId_ = sockId;
41 if (domain == AF_INET || domain == AF_INET6) {
42 int enable = 1;
43 if (setsockopt(sockId, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&enable),
44 sizeof(enable)) == SOCKET_ERROR) {
45 Close();
46 return false;
47 }
48 if (domain == AF_INET6) {
49 if (setsockopt(sockId, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<char*>(&enable),
50 sizeof(enable)) == SOCKET_ERROR) {
51 Close();
52 return false;
53 }
54 }
55 }
56 domain_ = domain;
57 TS_LOGI("CreateSocket socket ok, socket %d domain %d", sockId_, domain);
58 return true;
59 }
60
Bind(int port)61 bool HttpSocket::Bind(int port)
62 {
63 if (sockId_ == INVALID_SOCKET) {
64 TS_LOGE("the socket not created");
65 return false;
66 }
67
68 if (domain_ == AF_INET) {
69 struct sockaddr_in addr;
70 std::fill(reinterpret_cast<char*>(&addr), reinterpret_cast<char*>(&addr) + sizeof(addr), 0);
71 addr.sin_family = AF_INET;
72 addr.sin_addr.s_addr = htons(INADDR_ANY);
73 addr.sin_port = htons(static_cast<uint16_t>(port));
74 if (bind(sockId_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
75 TS_LOGE("bind ipv4 socket error, port %d: %d:%s", port, errno, strerror(errno));
76 return false;
77 }
78 } else if (domain_ == AF_INET6) {
79 struct sockaddr_in6 addr;
80 std::fill(reinterpret_cast<char*>(&addr), reinterpret_cast<char*>(&addr) + sizeof(addr), 0);
81 addr.sin6_family = AF_INET6;
82 addr.sin6_addr = in6addr_any;
83 addr.sin6_port = htons(static_cast<uint16_t>(port));
84 if (bind(sockId_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
85 TS_LOGE("bind ipv6 socket error, port %d: %d:%s", port, errno, strerror(errno));
86 return false;
87 }
88 } else {
89 return false;
90 }
91 TS_LOGI("bind socket ok, port %d", port);
92 return true;
93 }
94
Listen(int maxConn)95 bool HttpSocket::Listen(int maxConn)
96 {
97 if (listen(sockId_, maxConn) == SOCKET_ERROR) {
98 TS_LOGE("listen socket error: %d:%s", errno, strerror(errno));
99 return false;
100 }
101 TS_LOGI("listen socket ok, maxConn %d", maxConn);
102 return true;
103 }
104
Accept(HttpSocket & client)105 bool HttpSocket::Accept(HttpSocket& client)
106 {
107 int clientId = accept(sockId_, nullptr, nullptr);
108 if (clientId == INVALID_SOCKET) {
109 TS_LOGE("accept socket error: %d:%s", errno, strerror(errno));
110 return false;
111 }
112
113 client.domain_ = domain_;
114 client.sockId_ = clientId;
115 TS_LOGI("accept client socket id %d domain %d", clientId, domain_);
116 return true;
117 }
118
Recv(void * data,size_t & len)119 bool HttpSocket::Recv(void* data, size_t& len)
120 {
121 #ifdef _WIN32
122 ssize_t recvLen = recv(sockId_, static_cast<char*>(data), len, 0);
123 #else
124 ssize_t recvLen = recv(sockId_, data, len, 0);
125 #endif
126 if (recvLen == SOCKET_ERROR) {
127 if (errno == EAGAIN) {
128 recvLen = 0;
129 } else {
130 TS_LOGE("recv from socket(%d) error: %d:%s", sockId_, errno, strerror(errno));
131 return false;
132 }
133 } else if (recvLen == 0) {
134 TS_LOGI("client socket(%d) closed", sockId_);
135 return false;
136 }
137 len = recvLen;
138 TS_LOGD("Recv from socket(%d) len %zu", sockId_, len);
139 return true;
140 }
141
Send(const void * data,size_t len)142 bool HttpSocket::Send(const void* data, size_t len)
143 {
144 #ifdef _WIN32
145 ssize_t sendLen = send(sockId_, static_cast<const char*>(data), len, 0);
146 #else
147 ssize_t sendLen = send(sockId_, data, len, 0);
148 #endif
149 if (sendLen == SOCKET_ERROR) {
150 TS_LOGE("send to socket(%d) error: %d:%s", sockId_, errno, strerror(errno));
151 return false;
152 }
153 TS_LOGD("send to socket(%d) len %zu", sockId_, len);
154 return true;
155 }
156
Close()157 void HttpSocket::Close()
158 {
159 if (sockId_ == INVALID_SOCKET) {
160 return;
161 }
162 TS_LOGI("close socket(%d)", sockId_);
163 #ifdef _WIN32
164 if (closesocket(sockId_) == SOCKET_ERROR) {
165 #else
166 if (close(sockId_) == SOCKET_ERROR) {
167 #endif
168 TS_LOGE("close socket(%d) error: %d:%s", sockId_, errno, strerror(errno));
169 }
170 sockId_ = INVALID_SOCKET;
171 }
172 } // namespace TraceStreamer
173 } // namespace SysTuning
174