• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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