Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: net/tools/flip_server/tcp_socket_util.cc

Issue 2169503002: Remove flip_server. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/tools/flip_server/tcp_socket_util.h"
6
7 #include <arpa/inet.h>
8 #include <errno.h>
9 #include <netdb.h>
10 #include <netinet/in.h>
11 #include <netinet/tcp.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/socket.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17
18 #include "base/files/file_util.h"
19 #include "base/logging.h"
20 #include "net/socket/tcp_socket.h"
21
22 namespace net {
23
24 namespace {
25
26 // Used to ensure we delete the addrinfo structure alloc'd by getaddrinfo().
27 class AddrinfoGuard {
28 public:
29 explicit AddrinfoGuard(struct addrinfo* addrinfo_ptr)
30 : addrinfo_ptr_(addrinfo_ptr) {}
31
32 ~AddrinfoGuard() { freeaddrinfo(addrinfo_ptr_); }
33
34 private:
35 struct addrinfo* addrinfo_ptr_;
36 };
37
38 // Summary:
39 // Closes a socket, with option to attempt it multiple times.
40 // Why do this? Well, if the system-call gets interrupted, close
41 // can fail with EINTR. In that case you should just retry.. Unfortunately,
42 // we can't be sure that errno is properly set since we're using a
43 // multithreaded approach in the filter proxy, so we should just retry.
44 // Args:
45 // fd - the socket to close
46 // tries - the number of tries to close the socket.
47 // Returns:
48 // true - if socket was closed
49 // false - if socket was NOT closed.
50 // Side-effects:
51 // sets *fd to -1 if socket was closed.
52 //
53 bool CloseSocket(int* fd, int tries) {
54 for (int i = 0; i < tries; ++i) {
55 if (!close(*fd)) {
56 *fd = -1;
57 return true;
58 }
59 }
60 return false;
61 }
62
63 } // namespace
64
65 int CreateTCPServerSocket(const std::string& host,
66 const std::string& port,
67 bool is_numeric_host_address,
68 int backlog,
69 bool reuseaddr,
70 bool reuseport,
71 bool wait_for_iface,
72 bool disable_nagle,
73 int* listen_fd) {
74 // start out by assuming things will fail.
75 *listen_fd = -1;
76
77 const char* node = NULL;
78 const char* service = NULL;
79
80 if (!host.empty())
81 node = host.c_str();
82 if (!port.empty())
83 service = port.c_str();
84
85 struct addrinfo* results = 0;
86 struct addrinfo hints;
87 memset(&hints, 0, sizeof(hints));
88
89 if (is_numeric_host_address) {
90 hints.ai_flags = AI_NUMERICHOST; // iff you know the name is numeric.
91 }
92 hints.ai_flags |= AI_PASSIVE;
93
94 hints.ai_family = PF_INET;
95 hints.ai_socktype = SOCK_STREAM;
96
97 int err = 0;
98 if ((err = getaddrinfo(node, service, &hints, &results))) {
99 // gai_strerror -is- threadsafe, so we get to use it here.
100 LOG(ERROR) << "getaddrinfo "
101 << " for (" << host << ":" << port << ") " << gai_strerror(err)
102 << "\n";
103 return -1;
104 }
105 // this will delete the addrinfo memory when we return from this function.
106 AddrinfoGuard addrinfo_guard(results);
107
108 int sock =
109 socket(results->ai_family, results->ai_socktype, results->ai_protocol);
110 if (sock == -1) {
111 LOG(ERROR) << "Unable to create socket for (" << host << ":" << port
112 << "): " << strerror(errno) << "\n";
113 return -1;
114 }
115
116 if (reuseaddr) {
117 // set SO_REUSEADDR on the listening socket.
118 int on = 1;
119 int rc;
120 rc = setsockopt(sock,
121 SOL_SOCKET,
122 SO_REUSEADDR,
123 reinterpret_cast<char*>(&on),
124 sizeof(on));
125 if (rc < 0) {
126 close(sock);
127 LOG(FATAL) << "setsockopt() failed fd=" << listen_fd << "\n";
128 }
129 }
130 #ifndef SO_REUSEPORT
131 #define SO_REUSEPORT 15
132 #endif
133 if (reuseport) {
134 // set SO_REUSEPORT on the listening socket.
135 int on = 1;
136 int rc;
137 rc = setsockopt(sock,
138 SOL_SOCKET,
139 SO_REUSEPORT,
140 reinterpret_cast<char*>(&on),
141 sizeof(on));
142 if (rc < 0) {
143 close(sock);
144 LOG(FATAL) << "setsockopt() failed fd=" << listen_fd << "\n";
145 }
146 }
147
148 if (bind(sock, results->ai_addr, results->ai_addrlen)) {
149 // If we are waiting for the interface to be raised, such as in an
150 // HA environment, ignore reporting any errors.
151 int saved_errno = errno;
152 if (!wait_for_iface || errno != EADDRNOTAVAIL) {
153 LOG(ERROR) << "Bind was unsuccessful for (" << host << ":" << port
154 << "): " << strerror(errno) << "\n";
155 }
156 // if we knew that we were not multithreaded, we could do the following:
157 // " : " << strerror(errno) << "\n";
158 if (CloseSocket(&sock, 100)) {
159 if (saved_errno == EADDRNOTAVAIL) {
160 return -3;
161 }
162 return -2;
163 } else {
164 // couldn't even close the dang socket?!
165 LOG(ERROR) << "Unable to close the socket.. Considering this a fatal "
166 "error, and exiting\n";
167 exit(EXIT_FAILURE);
168 return -1;
169 }
170 }
171
172 if (disable_nagle) {
173 if (!SetTCPNoDelay(sock, /*no_delay=*/true)) {
174 close(sock);
175 LOG(FATAL) << "SetTCPNoDelay() failed on fd: " << sock;
176 return -1;
177 }
178 }
179
180 if (listen(sock, backlog)) {
181 // listen was unsuccessful.
182 LOG(ERROR) << "Listen was unsuccessful for (" << host << ":" << port
183 << "): " << strerror(errno) << "\n";
184 // if we knew that we were not multithreaded, we could do the following:
185 // " : " << strerror(errno) << "\n";
186
187 if (CloseSocket(&sock, 100)) {
188 sock = -1;
189 return -1;
190 } else {
191 // couldn't even close the dang socket?!
192 LOG(FATAL) << "Unable to close the socket.. Considering this a fatal "
193 "error, and exiting\n";
194 }
195 }
196
197 // If we've gotten to here, Yeay! Success!
198 *listen_fd = sock;
199
200 return 0;
201 }
202
203 int CreateTCPClientSocket(const std::string& host,
204 const std::string& port,
205 bool is_numeric_host_address,
206 bool disable_nagle,
207 int* connect_fd) {
208 const char* node = NULL;
209 const char* service = NULL;
210
211 *connect_fd = -1;
212 if (!host.empty())
213 node = host.c_str();
214 if (!port.empty())
215 service = port.c_str();
216
217 struct addrinfo* results = 0;
218 struct addrinfo hints;
219 memset(&hints, 0, sizeof(hints));
220
221 if (is_numeric_host_address)
222 hints.ai_flags = AI_NUMERICHOST; // iff you know the name is numeric.
223 hints.ai_flags |= AI_PASSIVE;
224
225 hints.ai_family = PF_INET;
226 hints.ai_socktype = SOCK_STREAM;
227
228 int err = 0;
229 if ((err = getaddrinfo(node, service, &hints, &results))) {
230 // gai_strerror -is- threadsafe, so we get to use it here.
231 LOG(ERROR) << "getaddrinfo for (" << node << ":" << service
232 << "): " << gai_strerror(err);
233 return -1;
234 }
235 // this will delete the addrinfo memory when we return from this function.
236 AddrinfoGuard addrinfo_guard(results);
237
238 int sock =
239 socket(results->ai_family, results->ai_socktype, results->ai_protocol);
240 if (sock == -1) {
241 LOG(ERROR) << "Unable to create socket for (" << node << ":" << service
242 << "): " << strerror(errno);
243 return -1;
244 }
245
246 if (!base::SetNonBlocking(sock)) {
247 LOG(FATAL) << "base::SetNonBlocking failed: " << sock;
248 }
249
250 if (disable_nagle) {
251 if (!SetTCPNoDelay(sock, /*no_delay=*/true)) {
252 close(sock);
253 LOG(FATAL) << "SetTCPNoDelay() failed on fd: " << sock;
254 return -1;
255 }
256 }
257
258 int ret_val = 0;
259 if (connect(sock, results->ai_addr, results->ai_addrlen)) {
260 if (errno != EINPROGRESS) {
261 LOG(ERROR) << "Connect was unsuccessful for (" << node << ":" << service
262 << "): " << strerror(errno);
263 close(sock);
264 return -1;
265 }
266 } else {
267 ret_val = 1;
268 }
269
270 // If we've gotten to here, Yeay! Success!
271 *connect_fd = sock;
272
273 return ret_val;
274 }
275
276 } // namespace net
OLDNEW
« no previous file with comments | « net/tools/flip_server/tcp_socket_util.h ('k') | net/tools/flip_server/url_to_filename_encoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698