1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "shill/http_proxy.h"
18
19 #include <errno.h>
20 #include <netinet/in.h>
21 #include <linux/if.h> // NOLINT - Needs definitions from netinet/in.h
22 #include <stdio.h>
23 #include <time.h>
24
25 #include <string>
26 #include <vector>
27
28 #include <base/bind.h>
29 #include <base/strings/string_number_conversions.h>
30 #include <base/strings/string_split.h>
31 #include <base/strings/string_util.h>
32 #include <base/strings/stringprintf.h>
33
34 #include "shill/async_connection.h"
35 #include "shill/connection.h"
36 #include "shill/dns_client.h"
37 #include "shill/event_dispatcher.h"
38 #include "shill/logging.h"
39 #include "shill/net/ip_address.h"
40 #include "shill/net/sockets.h"
41
42 using base::Bind;
43 using base::StringPrintf;
44 using std::string;
45 using std::vector;
46
47 namespace shill {
48
49 namespace Logging {
50 static auto kModuleLogScope = ScopeLogger::kHTTPProxy;
ObjectID(Connection * c)51 static string ObjectID(Connection* c) {
52 return c->interface_name();
53 }
54 }
55
56 const int HTTPProxy::kClientHeaderTimeoutSeconds = 1;
57 const int HTTPProxy::kConnectTimeoutSeconds = 10;
58 const int HTTPProxy::kDNSTimeoutSeconds = 5;
59 const int HTTPProxy::kDefaultServerPort = 80;
60 const int HTTPProxy::kInputTimeoutSeconds = 30;
61 const size_t HTTPProxy::kMaxClientQueue = 10;
62 const size_t HTTPProxy::kMaxHeaderCount = 128;
63 const size_t HTTPProxy::kMaxHeaderSize = 2048;
64 const int HTTPProxy::kTransactionTimeoutSeconds = 600;
65
66 const char HTTPProxy::kHTTPMethodConnect[] = "connect";
67 const char HTTPProxy::kHTTPMethodTerminator[] = " ";
68 const char HTTPProxy::kHTTPURLDelimiters[] = " /#?";
69 const char HTTPProxy::kHTTPURLPrefix[] = "http://";
70 const char HTTPProxy::kHTTPVersionPrefix[] = " HTTP/1";
71 const char HTTPProxy::kInternalErrorMsg[] = "Proxy Failed: Internal Error";
72
HTTPProxy(ConnectionRefPtr connection)73 HTTPProxy::HTTPProxy(ConnectionRefPtr connection)
74 : state_(kStateIdle),
75 connection_(connection),
76 weak_ptr_factory_(this),
77 accept_callback_(Bind(&HTTPProxy::AcceptClient,
78 weak_ptr_factory_.GetWeakPtr())),
79 connect_completion_callback_(Bind(&HTTPProxy::OnConnectCompletion,
80 weak_ptr_factory_.GetWeakPtr())),
81 dns_client_callback_(Bind(&HTTPProxy::GetDNSResult,
82 weak_ptr_factory_.GetWeakPtr())),
83 read_client_callback_(Bind(&HTTPProxy::ReadFromClient,
84 weak_ptr_factory_.GetWeakPtr())),
85 read_server_callback_(Bind(&HTTPProxy::ReadFromServer,
86 weak_ptr_factory_.GetWeakPtr())),
87 write_client_callback_(Bind(&HTTPProxy::WriteToClient,
88 weak_ptr_factory_.GetWeakPtr())),
89 write_server_callback_(Bind(&HTTPProxy::WriteToServer,
90 weak_ptr_factory_.GetWeakPtr())),
91 dispatcher_(nullptr),
92 proxy_port_(-1),
93 proxy_socket_(-1),
94 sockets_(nullptr),
95 client_socket_(-1),
96 server_port_(kDefaultServerPort),
97 server_socket_(-1),
98 is_route_requested_(false) { }
99
~HTTPProxy()100 HTTPProxy::~HTTPProxy() {
101 Stop();
102 }
103
Start(EventDispatcher * dispatcher,Sockets * sockets)104 bool HTTPProxy::Start(EventDispatcher* dispatcher,
105 Sockets* sockets) {
106 SLOG(connection_.get(), 3) << "In " << __func__;
107
108 if (sockets_) {
109 // We are already running.
110 return true;
111 }
112
113 proxy_socket_ = sockets->Socket(PF_INET, SOCK_STREAM, 0);
114 if (proxy_socket_ < 0) {
115 PLOG(ERROR) << "Failed to open proxy socket";
116 return false;
117 }
118
119 struct sockaddr_in addr;
120 socklen_t addrlen = sizeof(addr);
121 memset(&addr, 0, sizeof(addr));
122 addr.sin_family = AF_INET;
123 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
124 if (sockets->Bind(proxy_socket_,
125 reinterpret_cast<struct sockaddr*>(&addr),
126 sizeof(addr)) < 0 ||
127 sockets->GetSockName(proxy_socket_,
128 reinterpret_cast<struct sockaddr*>(&addr),
129 &addrlen) < 0 ||
130 sockets->SetNonBlocking(proxy_socket_) < 0 ||
131 sockets->Listen(proxy_socket_, kMaxClientQueue) < 0) {
132 sockets->Close(proxy_socket_);
133 proxy_socket_ = -1;
134 PLOG(ERROR) << "HTTPProxy socket setup failed";
135 return false;
136 }
137
138 accept_handler_.reset(
139 dispatcher->CreateReadyHandler(proxy_socket_, IOHandler::kModeInput,
140 accept_callback_));
141 dispatcher_ = dispatcher;
142 dns_client_.reset(new DNSClient(IPAddress::kFamilyIPv4,
143 connection_->interface_name(),
144 connection_->dns_servers(),
145 kDNSTimeoutSeconds * 1000,
146 dispatcher,
147 dns_client_callback_));
148 proxy_port_ = ntohs(addr.sin_port);
149 server_async_connection_.reset(
150 new AsyncConnection(connection_->interface_name(), dispatcher, sockets,
151 connect_completion_callback_));
152 sockets_ = sockets;
153 state_ = kStateWaitConnection;
154 return true;
155 }
156
Stop()157 void HTTPProxy::Stop() {
158 SLOG(connection_.get(), 3) << "In " << __func__;
159
160 if (!sockets_) {
161 return;
162 }
163
164 StopClient();
165
166 accept_handler_.reset();
167 dispatcher_ = nullptr;
168 dns_client_.reset();
169 proxy_port_ = -1;
170 server_async_connection_.reset();
171 sockets_->Close(proxy_socket_);
172 proxy_socket_ = -1;
173 sockets_ = nullptr;
174 state_ = kStateIdle;
175 }
176
177 // IOReadyHandler callback routine fired when a client connects to the
178 // proxy's socket. We Accept() the client and start reading a request
179 // from it.
AcceptClient(int fd)180 void HTTPProxy::AcceptClient(int fd) {
181 SLOG(connection_.get(), 3) << "In " << __func__;
182
183 int client_fd = sockets_->Accept(fd, nullptr, nullptr);
184 if (client_fd < 0) {
185 PLOG(ERROR) << "Client accept failed";
186 return;
187 }
188
189 accept_handler_->Stop();
190
191 client_socket_ = client_fd;
192
193 sockets_->SetNonBlocking(client_socket_);
194 read_client_handler_.reset(dispatcher_->CreateInputHandler(
195 client_socket_,
196 read_client_callback_,
197 Bind(&HTTPProxy::OnReadError, weak_ptr_factory_.GetWeakPtr())));
198 // Overall transaction timeout.
199 transaction_timeout_.Reset(Bind(&HTTPProxy::StopClient,
200 weak_ptr_factory_.GetWeakPtr()));
201 dispatcher_->PostDelayedTask(transaction_timeout_.callback(),
202 kTransactionTimeoutSeconds * 1000);
203
204 state_ = kStateReadClientHeader;
205 StartIdleTimeout();
206 }
207
ConnectServer(const IPAddress & address,int port)208 bool HTTPProxy::ConnectServer(const IPAddress& address, int port) {
209 state_ = kStateConnectServer;
210 if (!server_async_connection_->Start(address, port)) {
211 SendClientError(500, "Could not create socket to connect to server");
212 return false;
213 }
214 StartIdleTimeout();
215 return true;
216 }
217
218 // DNSClient callback that fires when the DNS request completes.
GetDNSResult(const Error & error,const IPAddress & address)219 void HTTPProxy::GetDNSResult(const Error& error, const IPAddress& address) {
220 if (!error.IsSuccess()) {
221 SendClientError(502, string("Could not resolve hostname: ") +
222 error.message());
223 return;
224 }
225 ConnectServer(address, server_port_);
226 }
227
228 // IOReadyHandler callback routine which fires when the asynchronous Connect()
229 // to the remote server completes (or fails).
OnConnectCompletion(bool success,int fd)230 void HTTPProxy::OnConnectCompletion(bool success, int fd) {
231 if (!success) {
232 SendClientError(500, string("Socket connection delayed failure: ") +
233 server_async_connection_->error());
234 return;
235 }
236 server_socket_ = fd;
237 state_ = kStateTunnelData;
238
239 // If this was a "CONNECT" request, notify the client that the connection
240 // has been established by sending an "OK" response.
241 if (base::LowerCaseEqualsASCII(client_method_, kHTTPMethodConnect)) {
242 SetClientResponse(200, "OK", "", "");
243 StartReceive();
244 }
245
246 StartTransmit();
247 }
248
OnReadError(const string & error_msg)249 void HTTPProxy::OnReadError(const string& error_msg) {
250 StopClient();
251 }
252
253 // Read through the header lines from the client, modifying or adding
254 // lines as necessary. Perform final determination of the hostname/port
255 // we should connect to and either start a DNS request or connect to a
256 // numeric address.
ParseClientRequest()257 bool HTTPProxy::ParseClientRequest() {
258 SLOG(connection_.get(), 3) << "In " << __func__;
259
260 string host;
261 bool found_via = false;
262 bool found_connection = false;
263 for (auto& header : client_headers_) {
264 if (base::StartsWith(header, "Host:",
265 base::CompareCase::INSENSITIVE_ASCII)) {
266 host = header.substr(5);
267 } else if (base::StartsWith(header, "Via:",
268 base::CompareCase::INSENSITIVE_ASCII)) {
269 found_via = true;
270 header.append(StringPrintf(", %s shill-proxy", client_version_.c_str()));
271 } else if (base::StartsWith(header, "Connection:",
272 base::CompareCase::INSENSITIVE_ASCII)) {
273 found_connection = true;
274 header.assign("Connection: close");
275 } else if (base::StartsWith(header, "Proxy-Connection:",
276 base::CompareCase::INSENSITIVE_ASCII)) {
277 header.assign("Proxy-Connection: close");
278 }
279 }
280
281 if (!found_connection) {
282 client_headers_.push_back("Connection: close");
283 }
284 if (!found_via) {
285 client_headers_.push_back(
286 StringPrintf("Via: %s shill-proxy", client_version_.c_str()));
287 }
288
289 // Assemble the request as it will be sent to the server.
290 client_data_.Clear();
291 if (!base::LowerCaseEqualsASCII(client_method_, kHTTPMethodConnect)) {
292 for (const auto& header : client_headers_) {
293 client_data_.Append(ByteString(header + "\r\n", false));
294 }
295 client_data_.Append(ByteString(string("\r\n"), false));
296 }
297
298 base::TrimWhitespaceASCII(host, base::TRIM_ALL, &host);
299 if (host.empty()) {
300 // Revert to using the hostname in the URL if no "Host:" header exists.
301 host = server_hostname_;
302 }
303
304 if (host.empty()) {
305 SendClientError(400, "I don't know what host you want me to connect to");
306 return false;
307 }
308
309 server_port_ = 80;
310 vector<string> host_parts = base::SplitString(
311 host, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
312
313 if (host_parts.size() > 2) {
314 SendClientError(400, "Too many colons in hostname");
315 return false;
316 } else if (host_parts.size() == 2) {
317 server_hostname_ = host_parts[0];
318 if (!base::StringToInt(host_parts[1], &server_port_)) {
319 SendClientError(400, "Could not parse port number");
320 return false;
321 }
322 } else {
323 server_hostname_ = host;
324 }
325
326 connection_->RequestRouting();
327 is_route_requested_ = true;
328
329 IPAddress addr(IPAddress::kFamilyIPv4);
330 if (addr.SetAddressFromString(server_hostname_)) {
331 if (!ConnectServer(addr, server_port_)) {
332 return false;
333 }
334 } else {
335 SLOG(connection_.get(), 3) << "Looking up host: " << server_hostname_;
336 Error error;
337 if (!dns_client_->Start(server_hostname_, &error)) {
338 SendClientError(502, "Could not resolve hostname: " + error.message());
339 return false;
340 }
341 state_ = kStateLookupServer;
342 }
343 return true;
344 }
345
346 // Accept a new line into the client headers. Returns false if a parse
347 // error occurs.
ProcessLastHeaderLine()348 bool HTTPProxy::ProcessLastHeaderLine() {
349 string* header = &client_headers_.back();
350 base::TrimString(*header, "\r", header);
351
352 if (header->empty()) {
353 // Empty line terminates client headers.
354 client_headers_.pop_back();
355 if (!ParseClientRequest()) {
356 return false;
357 }
358 }
359
360 // Is this is the first header line?
361 if (client_headers_.size() == 1) {
362 if (!ReadClientHTTPMethod(header) ||
363 !ReadClientHTTPVersion(header) ||
364 !ReadClientHostname(header)) {
365 return false;
366 }
367 }
368
369 if (client_headers_.size() >= kMaxHeaderCount) {
370 SendClientError(500, kInternalErrorMsg);
371 return false;
372 }
373
374 return true;
375 }
376
377 // Split input from client into header lines, and consume parsed lines
378 // from InputData. The passed in |data| is modified to indicate the
379 // characters consumed.
ReadClientHeaders(InputData * data)380 bool HTTPProxy::ReadClientHeaders(InputData* data) {
381 unsigned char* ptr = data->buf;
382 unsigned char* end = ptr + data->len;
383
384 if (client_headers_.empty()) {
385 client_headers_.push_back(string());
386 }
387
388 for (; ptr < end && state_ == kStateReadClientHeader; ++ptr) {
389 if (*ptr == '\n') {
390 if (!ProcessLastHeaderLine()) {
391 return false;
392 }
393
394 // Start a new line. New chararacters we receive will be appended there.
395 client_headers_.push_back(string());
396 continue;
397 }
398
399 string* header = &client_headers_.back();
400 // Is the first character of the header line a space or tab character?
401 if (header->empty() && (*ptr == ' ' || *ptr == '\t') &&
402 client_headers_.size() > 1) {
403 // Line Continuation: Add this character to the previous header line.
404 // This way, all of the data (including newlines and line continuation
405 // characters) related to a specific header will be contained within
406 // a single element of |client_headers_|, and manipulation of headers
407 // such as appending will be simpler. This is accomplished by removing
408 // the empty line we started, and instead appending the whitespace
409 // and following characters to the previous line.
410 client_headers_.pop_back();
411 header = &client_headers_.back();
412 header->append("\r\n");
413 }
414
415 if (header->length() >= kMaxHeaderSize) {
416 SendClientError(500, kInternalErrorMsg);
417 return false;
418 }
419 header->push_back(*ptr);
420 }
421
422 // Return the remaining data to the caller -- this could be POST data
423 // or other non-header data sent with the client request.
424 data->buf = ptr;
425 data->len = end - ptr;
426
427 return true;
428 }
429
430 // Finds the URL in the first line of an HTTP client header, and extracts
431 // and removes the hostname (and port) from the URL. Returns false if a
432 // parse error occurs, and true otherwise (whether or not the hostname was
433 // found).
ReadClientHostname(string * header)434 bool HTTPProxy::ReadClientHostname(string* header) {
435 const string http_url_prefix(kHTTPURLPrefix);
436 size_t url_idx = header->find(http_url_prefix);
437 if (url_idx != string::npos) {
438 size_t host_start = url_idx + http_url_prefix.length();
439 size_t host_end =
440 header->find_first_of(kHTTPURLDelimiters, host_start);
441 if (host_end != string::npos) {
442 server_hostname_ = header->substr(host_start,
443 host_end - host_start);
444 // Modify the URL passed upstream to remove "http://<hostname>".
445 header->erase(url_idx, host_end - url_idx);
446 if ((*header)[url_idx] != '/') {
447 header->insert(url_idx, "/");
448 }
449 } else {
450 LOG(ERROR) << "Could not find end of hostname in request. Line was: "
451 << *header;
452 SendClientError(500, kInternalErrorMsg);
453 return false;
454 }
455 }
456 return true;
457 }
458
ReadClientHTTPMethod(string * header)459 bool HTTPProxy::ReadClientHTTPMethod(string* header) {
460 size_t method_end = header->find(kHTTPMethodTerminator);
461 if (method_end == string::npos || method_end == 0) {
462 LOG(ERROR) << "Could not parse HTTP method. Line was: " << *header;
463 SendClientError(501, "Server could not parse HTTP method");
464 return false;
465 }
466 client_method_ = header->substr(0, method_end);
467 return true;
468 }
469
470 // Extract the HTTP version number from the first line of the client headers.
471 // Returns true if found.
ReadClientHTTPVersion(string * header)472 bool HTTPProxy::ReadClientHTTPVersion(string* header) {
473 const string http_version_prefix(kHTTPVersionPrefix);
474 size_t http_ver_pos = header->find(http_version_prefix);
475 if (http_ver_pos != string::npos) {
476 client_version_ =
477 header->substr(http_ver_pos + http_version_prefix.length() - 1);
478 } else {
479 SendClientError(501, "Server only accepts HTTP/1.x requests");
480 return false;
481 }
482 return true;
483 }
484
485 // IOInputHandler callback that fires when data is read from the client.
486 // This could be header data, or perhaps POST data that follows the headers.
ReadFromClient(InputData * data)487 void HTTPProxy::ReadFromClient(InputData* data) {
488 SLOG(connection_.get(), 3) << "In " << __func__ << " length " << data->len;
489
490 if (data->len == 0) {
491 // EOF from client.
492 StopClient();
493 return;
494 }
495
496 if (state_ == kStateReadClientHeader) {
497 if (!ReadClientHeaders(data)) {
498 return;
499 }
500 if (state_ == kStateReadClientHeader) {
501 // Still consuming client headers; restart the input timer.
502 StartIdleTimeout();
503 return;
504 }
505 }
506
507 // Check data->len again since ReadClientHeaders() may have consumed some
508 // part of it.
509 if (data->len != 0) {
510 // The client sent some information after its headers. Buffer the client
511 // input and temporarily disable input events from the client.
512 client_data_.Append(ByteString(data->buf, data->len));
513 read_client_handler_->Stop();
514 StartTransmit();
515 }
516 }
517
518 // IOInputHandler callback which fires when data has been read from the
519 // server.
ReadFromServer(InputData * data)520 void HTTPProxy::ReadFromServer(InputData* data) {
521 SLOG(connection_.get(), 3) << "In " << __func__ << " length " << data->len;
522 if (data->len == 0) {
523 // Server closed connection.
524 if (server_data_.IsEmpty()) {
525 StopClient();
526 return;
527 }
528 state_ = kStateFlushResponse;
529 } else {
530 read_server_handler_->Stop();
531 }
532
533 server_data_.Append(ByteString(data->buf, data->len));
534
535 StartTransmit();
536 }
537
538 // Return an HTTP error message back to the client.
SendClientError(int code,const string & error)539 void HTTPProxy::SendClientError(int code, const string& error) {
540 SLOG(connection_.get(), 3) << "In " << __func__;
541 LOG(ERROR) << "Sending error " << error;
542 SetClientResponse(code, "ERROR", "text/plain", error);
543 state_ = kStateFlushResponse;
544 StartTransmit();
545 }
546
547 // Create an HTTP response message to be sent to the client.
SetClientResponse(int code,const string & type,const string & content_type,const string & message)548 void HTTPProxy::SetClientResponse(int code, const string& type,
549 const string& content_type,
550 const string& message) {
551 string content_line;
552 if (!message.empty() && !content_type.empty()) {
553 content_line = StringPrintf("Content-Type: %s\r\n", content_type.c_str());
554 }
555 string response = StringPrintf("HTTP/1.1 %d %s\r\n"
556 "%s\r\n"
557 "%s", code, type.c_str(),
558 content_line.c_str(),
559 message.c_str());
560 server_data_ = ByteString(response, false);
561 }
562
563 // Start a timeout for "the next event". This timeout augments the overall
564 // transaction timeout to make sure there is some activity occurring at
565 // reasonable intervals.
StartIdleTimeout()566 void HTTPProxy::StartIdleTimeout() {
567 int timeout_seconds = 0;
568 switch (state_) {
569 case kStateReadClientHeader:
570 timeout_seconds = kClientHeaderTimeoutSeconds;
571 break;
572 case kStateConnectServer:
573 timeout_seconds = kConnectTimeoutSeconds;
574 break;
575 case kStateLookupServer:
576 // DNSClient has its own internal timeout, so we need not set one here.
577 timeout_seconds = 0;
578 break;
579 default:
580 timeout_seconds = kInputTimeoutSeconds;
581 break;
582 }
583 idle_timeout_.Cancel();
584 if (timeout_seconds != 0) {
585 idle_timeout_.Reset(Bind(&HTTPProxy::StopClient,
586 weak_ptr_factory_.GetWeakPtr()));
587 dispatcher_->PostDelayedTask(idle_timeout_.callback(),
588 timeout_seconds * 1000);
589 }
590 }
591
592 // Start the various input handlers. Listen for new data only if we have
593 // completely written the last data we've received to the other end.
StartReceive()594 void HTTPProxy::StartReceive() {
595 if (state_ == kStateTunnelData && client_data_.IsEmpty()) {
596 read_client_handler_->Start();
597 }
598 if (server_data_.IsEmpty()) {
599 if (state_ == kStateTunnelData) {
600 if (read_server_handler_.get()) {
601 read_server_handler_->Start();
602 } else {
603 read_server_handler_.reset(dispatcher_->CreateInputHandler(
604 server_socket_,
605 read_server_callback_,
606 Bind(&HTTPProxy::OnReadError, weak_ptr_factory_.GetWeakPtr())));
607 }
608 } else if (state_ == kStateFlushResponse) {
609 StopClient();
610 return;
611 }
612 }
613 StartIdleTimeout();
614 }
615
616 // Start the various output-ready handlers for the endpoints we have
617 // data waiting for.
StartTransmit()618 void HTTPProxy::StartTransmit() {
619 if (state_ == kStateTunnelData && !client_data_.IsEmpty()) {
620 if (write_server_handler_.get()) {
621 write_server_handler_->Start();
622 } else {
623 write_server_handler_.reset(
624 dispatcher_->CreateReadyHandler(server_socket_,
625 IOHandler::kModeOutput,
626 write_server_callback_));
627 }
628 }
629 if ((state_ == kStateFlushResponse || state_ == kStateTunnelData) &&
630 !server_data_.IsEmpty()) {
631 if (write_client_handler_.get()) {
632 write_client_handler_->Start();
633 } else {
634 write_client_handler_.reset(
635 dispatcher_->CreateReadyHandler(client_socket_,
636 IOHandler::kModeOutput,
637 write_client_callback_));
638 }
639 }
640 StartIdleTimeout();
641 }
642
643 // End the transaction with the current client, restart the IOHandler
644 // which alerts us to new clients connecting. This function is called
645 // during various error conditions and is a callback for all timeouts.
StopClient()646 void HTTPProxy::StopClient() {
647 SLOG(connection_.get(), 3) << "In " << __func__;
648
649 if (is_route_requested_) {
650 connection_->ReleaseRouting();
651 is_route_requested_ = false;
652 }
653 write_client_handler_.reset();
654 read_client_handler_.reset();
655 if (client_socket_ != -1) {
656 sockets_->Close(client_socket_);
657 client_socket_ = -1;
658 }
659 client_headers_.clear();
660 client_method_.clear();
661 client_version_.clear();
662 server_port_ = kDefaultServerPort;
663 write_server_handler_.reset();
664 read_server_handler_.reset();
665 if (server_socket_ != -1) {
666 sockets_->Close(server_socket_);
667 server_socket_ = -1;
668 }
669 server_hostname_.clear();
670 client_data_.Clear();
671 server_data_.Clear();
672 dns_client_->Stop();
673 server_async_connection_->Stop();
674 idle_timeout_.Cancel();
675 transaction_timeout_.Cancel();
676 accept_handler_->Start();
677 state_ = kStateWaitConnection;
678 }
679
680 // Output ReadyHandler callback which fires when the client socket is
681 // ready for data to be sent to it.
WriteToClient(int fd)682 void HTTPProxy::WriteToClient(int fd) {
683 CHECK_EQ(client_socket_, fd);
684 int ret = sockets_->Send(fd, server_data_.GetConstData(),
685 server_data_.GetLength(), 0);
686 SLOG(connection_.get(), 3) << "In " << __func__ << " wrote " << ret << " of "
687 << server_data_.GetLength();
688 if (ret < 0) {
689 LOG(ERROR) << "Server write failed";
690 StopClient();
691 return;
692 }
693
694 server_data_ = ByteString(server_data_.GetConstData() + ret,
695 server_data_.GetLength() - ret);
696
697 if (server_data_.IsEmpty()) {
698 write_client_handler_->Stop();
699 }
700
701 StartReceive();
702 }
703
704 // Output ReadyHandler callback which fires when the server socket is
705 // ready for data to be sent to it.
WriteToServer(int fd)706 void HTTPProxy::WriteToServer(int fd) {
707 CHECK_EQ(server_socket_, fd);
708 int ret = sockets_->Send(fd, client_data_.GetConstData(),
709 client_data_.GetLength(), 0);
710 SLOG(connection_.get(), 3) << "In " << __func__ << " wrote " << ret << " of "
711 << client_data_.GetLength();
712
713 if (ret < 0) {
714 LOG(ERROR) << "Client write failed";
715 StopClient();
716 return;
717 }
718
719 client_data_ = ByteString(client_data_.GetConstData() + ret,
720 client_data_.GetLength() - ret);
721
722 if (client_data_.IsEmpty()) {
723 write_server_handler_->Stop();
724 }
725
726 StartReceive();
727 }
728
729 } // namespace shill
730