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; 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 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 100 HTTPProxy::~HTTPProxy() { 101 Stop(); 102 } 103 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 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. 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 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. 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). 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 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. 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. 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. 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). 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 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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